/* 
 * Hisotry 
 * modify zhanghua at 2000/10/10 for wrong auto_commit result at 9513 
 * */

// Oracle and ODBC Template Library, Version 3.1.20,
// Copyright (C) Sergei Kuchin, 1996,2000
// Author: Sergei Kuchin
// This library is free software. Permission to use, copy,
// modify and redistribute it for any purpose is hereby granted
// without fee, provided that the above copyright notice appear
// in all copies.

#ifndef __OTL_H__
#define __OTL_H__
#pragma warning(disable:4348)

#include <string.h>
#include <ctype.h>
#include <stdlib.h>

//======================= CONFIGURATION #DEFINEs ===========================

// Uncomment the following line in order to include the OTL for ODBC:
//#define OTL_ODBC

// Uncomment the following line in order to include the OTL for
// Oracle 7:
//#define OTL_ORA7

// Uncomment the following line in order to include the OTL for
// Oracle 8:
//#define OTL_ORA8

// Uncomment the following line in order to include the OTL for
// Oracle 8i:
//#define OTL_ORA8I

// The macro definitions may be also turned on via C++ compiler command line
// option, e.g.: -DOTL_ODBC, -DOTL_ORA7, -DOTL_ORA8, -DOTL_ORA8I

#ifdef OTL_ORA8I
#define OTL_ORA8
#define OTL_ORA8_8I_REFCUR
#define OTL_ORA8_8I_DESC_COLUMN_SCALE
#endif

// ===== defined(OTL_ODBC) && !defined(OTL_ORA8) && !defined(OTL_ORA7)
#ifdef OTL_ODBC
#ifndef OTL_ORA8
#ifndef OTL_ORA7

#define OTL_ODBC_NAMESPACE_BEGIN
#define OTL_ODBC_NAMESPACE_PREFIX
#define OTL_ODBC_NAMESPACE_END

#define OTL_ORA7_NAMESPACE_BEGIN
#define OTL_ORA7_NAMESPACE_PREFIX
#define OTL_ORA7_NAMESPACE_END

#define OTL_ORA8_NAMESPACE_BEGIN
#define OTL_ORA8_NAMESPACE_PREFIX
#define OTL_ORA8_NAMESPACE_END
#endif
#endif
#endif

// ===== defined(OTL_ORA7) && !defined(OTL_ODBC) && !defined(OTL_ORA8)
#ifdef OTL_ORA7
#ifndef OTL_ODBC
#ifndef OTL_ORA8

#define OTL_ODBC_NAMESPACE_BEGIN
#define OTL_ODBC_NAMESPACE_PREFIX
#define OTL_ODBC_NAMESPACE_END

#define OTL_ORA7_NAMESPACE_BEGIN
#define OTL_ORA7_NAMESPACE_PREFIX
#define OTL_ORA7_NAMESPACE_END

#define OTL_ORA8_NAMESPACE_BEGIN
#define OTL_ORA8_NAMESPACE_PREFIX
#define OTL_ORA8_NAMESPACE_END
#endif
#endif
#endif

// ===== defined(OTL_ORA8) && !defined(OTL_ODBC) && !defined(OTL_ORA7)
#ifdef OTL_ORA8
#ifndef OTL_ODBC
#ifndef OTL_ORA7

#define OTL_ODBC_NAMESPACE_BEGIN
#define OTL_ODBC_NAMESPACE_PREFIX
#define OTL_ODBC_NAMESPACE_END

#define OTL_ORA7_NAMESPACE_BEGIN
#define OTL_ORA7_NAMESPACE_PREFIX
#define OTL_ORA7_NAMESPACE_END

#define OTL_ORA8_NAMESPACE_BEGIN
#define OTL_ORA8_NAMESPACE_PREFIX
#define OTL_ORA8_NAMESPACE_END
#endif
#endif
#endif

// ===== defined(OTL_ODBC) && defined(OTL_ORA7) && !defined(OTL_ORA8)
#ifdef OTL_ODBC
#ifdef OTL_ORA7
#ifndef OTL_ORA8

#define OTL_ODBC_NAMESPACE_BEGIN namespace odbc{
#define OTL_ODBC_NAMESPACE_PREFIX odbc::
#define OTL_ODBC_NAMESPACE_END }

#define OTL_ORA7_NAMESPACE_BEGIN namespace oracle {
#define OTL_ORA7_NAMESPACE_PREFIX oracle::
#define OTL_ORA7_NAMESPACE_END }

#define OTL_ORA8_NAMESPACE_BEGIN
#define OTL_ORA8_NAMESPACE_PREFIX
#define OTL_ORA8_NAMESPACE_END
#endif
#endif
#endif

// ===== defined(OTL_ODBC) && defined(OTL_ORA8) && !defined(OTL_ORA7)
#ifdef OTL_ODBC
#ifdef OTL_ORA8
#ifndef OTL_ORA7

#define OTL_ODBC_NAMESPACE_BEGIN namespace odbc{
#define OTL_ODBC_NAMESPACE_PREFIX odbc::
#define OTL_ODBC_NAMESPACE_END }

#define OTL_ORA7_NAMESPACE_BEGIN
#define OTL_ORA7_NAMESPACE_PREFIX
#define OTL_ORA7_NAMESPACE_END

#define OTL_ORA8_NAMESPACE_BEGIN namespace oracle{
#define OTL_ORA8_NAMESPACE_PREFIX oracle::
#define OTL_ORA8_NAMESPACE_END }
#endif
#endif
#endif

#ifdef OTL_ORA7
#define OTL_PL_TAB
#endif

#ifdef OTL_ORA8
#define OTL_PL_TAB
#endif

//#define OTL_DEBUG

//======================= END OF CONFIGURATION ==============================

// ====== COMMON NON-TEMPLATE OBJECTS: CONSTANTS, CLASSES, ETC. ===========

#define OTL_UNUSED_ARG(a) {if(&a){}}

const int otl_var_list_size=512;

const int otl_error_code_0=32000;
#define otl_error_msg_0 "Incompatible data types in stream operation"

const int otl_error_code_1=32004;
#define otl_error_msg_1 "No input variables have been defined in SQL statement"

const int otl_error_code_2=32003;
#define otl_error_msg_2 "Not all input variables have been initialized"

const int otl_error_code_3=32001;
#define otl_error_msg_3 "Row must be full for flushing output stream"

const int otl_error_code_4=32005;
#define otl_error_msg_4 "Input string value is too large to fit into the buffer"

const int otl_error_code_5=32006;
#define otl_error_msg_5 "Input otl_long_string is too large to fit into the buffer"

const int otl_error_code_6=32007;
#define otl_error_msg_6 "PL/SQL table size is too large (>32767)"

const int otl_error_code_7=32008;
#define otl_error_msg_7 \
    "Writing CLOB/BLOB in stream mode: actual size is greater than specified"

const int otl_error_code_8=32009;
#define otl_error_msg_8 \
    "Closing CLOB/BLOB in stream mode: actual size is not equal to specified size"

const int otl_error_code_9=32010;
#define otl_error_msg_9 "CLOB/BLOB stream is not open for writing"

const int otl_error_code_10=32011;
#define otl_error_msg_10 "CLOB/BLOB stream is not open for reading"

const int otl_error_code_11=32012;
#define otl_error_msg_11 "First session must be started with session_begin()"

const int otl_explicit_select=0;
const int otl_implicit_select=1;

const int OTL_INPUT_PARAM=0;
const int OTL_OUTPUT_PARAM=1;
const int OTL_INOUT_PARAM=2;

const int otl_oracle_date_size=7;

class otl_select_struct_override
{
    public:

        int col_ndx[otl_var_list_size];
        int col_type[otl_var_list_size];
        int col_size[otl_var_list_size];
        int len;

        otl_select_struct_override(){len=0;}
        ~otl_select_struct_override(){}

        void add_override(const int andx, const int atype, const int asize=0)
        {
            if(len<otl_var_list_size-1)
            {
                ++len;
                col_ndx[len-1]=andx;
                col_type[len-1]=atype;
                col_size[len-1]=asize;
            }
        }

        int find(const int ndx)
        {
            int i;
            for(i=0;i<len;++i)
                if(ndx==col_ndx[i])
                    return i;
            return -1;
        }

};

class otl_datetime
{
    public:

        int year;
        int month;
        int day;
        int hour;
        int minute;
        int second;

        otl_datetime()
        {
            year=1900;
            month=1;
            day=1;
            hour=0;
            minute=0;
            second=0;
        }

        otl_datetime(const otl_datetime& dt)
        {
            year=dt.year;
            month=dt.month;
            day=dt.day;
            hour=dt.hour;
            minute=dt.minute;
            second=dt.second;
        }

        ~otl_datetime(){}

        otl_datetime& operator=(const otl_datetime& dt)
        {
            year=dt.year;
            month=dt.month;
            day=dt.day;
            hour=dt.hour;
            minute=dt.minute;
            second=dt.second;
            return *this;
        }

};

class otl_oracle_date
{
    public:
        unsigned char century;
        unsigned char year;
        unsigned char month;
        unsigned char day;
        unsigned char hour;
        unsigned char minute;
        unsigned char second;

        otl_oracle_date(){}
        ~otl_oracle_date(){}

};

#ifdef OTL_DEBUG
#include <iostream.h>
inline ostream& operator<<(ostream& s, const otl_datetime& dt)
{
    s<<dt.month<<"/"<<dt.day<<"/"<<dt.year<<" "
        <<dt.hour<<":"<<dt.minute<<":"<<dt.second;
    return s;
}
#endif

static inline void convert_date(otl_datetime& t,const otl_oracle_date& s)
{
    t.year=((int)(s.century-100)*100+((int)s.year-100));
    t.month=s.month;
    t.day=s.day;
    t.hour=s.hour-1;
    t.minute=s.minute-1;
    t.second=s.second-1;
}


static inline void convert_date(otl_oracle_date& t,const otl_datetime& s)
{
    t.year=(s.year%100)+100;
    t.century=(s.year/100)+100;
    t.month=s.month;
    t.day=s.day;
    t.hour=s.hour+1;
    t.minute=s.minute+1;
    t.second=s.second+1;
}


class otl_null
{
    public:
        int dummy;

        otl_null(){}
        ~otl_null(){}
};

class otl_column_desc
{
    public:
        char name[512];
        int  dbtype;
        int  otl_var_dbtype;
        int  dbsize;
        int  scale;
        int  prec;
        int  nullok;
};

class otl_var_desc
{
    public:
        int param_type;
        int ftype;
        int elem_size;
        int array_size;
        int pos;
        int name_pos;
        int pl_tab_flag;

        otl_var_desc()
        {
            param_type=0;
            ftype=0;
            elem_size=0;
            array_size=0;
            pos=0;
            name_pos=0;
            pl_tab_flag=0;
        }

        ~otl_var_desc(){}

};

const int otl_var_none=0;
const int otl_var_char=1;
const int otl_var_double=2;
const int otl_var_float=3;
const int otl_var_int=4;
const int otl_var_unsigned_int=5;
const int otl_var_short=6;
const int otl_var_long_int=7;
const int otl_var_timestamp=8;
const int otl_var_varchar_long=9;
const int otl_var_raw_long=10;
const int otl_var_clob=11;
const int otl_var_blob=12;
const int otl_var_refcur=13;
const int otl_var_long_string=15;

class otl_long_string
{
    public:

        unsigned char* v;
        int length;
        int extern_buffer_flag;
        int buf_size;

        otl_long_string(const int str_size=32760)
        {
            extern_buffer_flag=0;
            length=0;
            buf_size=str_size;
            v=new unsigned char[str_size+1];
            memset(v,0,str_size);
        }

        otl_long_string(const void* external_buffer, const int str_size)
        {
            extern_buffer_flag=1;
            length=0;
            buf_size=str_size;
            v=(unsigned char*)external_buffer;
        }

        ~otl_long_string()
        {
            if(!extern_buffer_flag)delete[] v;
        }

        void set_len(const int len=0){length=len;}
        int len(void){return length;}

        unsigned char& operator[](int ndx){return v[ndx];}

};

static inline const char* otl_var_type_name(const int ftype)
{
    static const char* const_CHAR="CHAR";
    static const char* const_DOUBLE="DOUBLE";
    static const char* const_FLOAT="FLOAT";
    static const char* const_INT="INT";
    static const char* const_UNSIGNED_INT="UNSIGNED INT";
    static const char* const_SHORT_INT="SHORT INT";
    static const char* const_LONG_INT="LONG INT";
    static const char* const_TIMESTAMP="TIMESTAMP";
    static const char* const_VARCHAR_LONG="VARCHAR LONG";
    static const char* const_RAW_LONG="RAW LONG";
    static const char* const_CLOB="CLOB";
    static const char* const_BLOB="BLOB";
    static const char* const_UNKNOWN="";
    static const char* const_LONG_STRING="otl_long_string()";

    switch(ftype)
    {
        case otl_var_char:
            return const_CHAR;
        case otl_var_double:
            return const_DOUBLE;
        case otl_var_float:
            return const_FLOAT;
        case otl_var_int:
            return const_INT;
        case otl_var_unsigned_int:
            return const_UNSIGNED_INT;
        case otl_var_short:
            return const_SHORT_INT;
        case otl_var_long_int:
            return const_LONG_INT;
        case otl_var_timestamp:
            return const_TIMESTAMP;
        case otl_var_varchar_long:
            return const_VARCHAR_LONG;
        case otl_var_raw_long:
            return const_RAW_LONG;
        case otl_var_clob:
            return const_CLOB;
        case otl_var_blob:
            return const_BLOB;
        case otl_var_long_string:
            return const_LONG_STRING;
        default:
            return const_UNKNOWN;
    }
}


static inline void otl_var_info_var
(const char* name,
const int ftype,
const int type_code,
char* var_info)
{
    char buf1[128];
    char buf2[128];
    strcpy(buf1,otl_var_type_name(ftype));
    strcpy(buf2,otl_var_type_name(type_code));
    strcpy(var_info,"Variable: ");
    strcat(var_info,name);
    strcat(var_info,"<");
    strcat(var_info,buf1);
    strcat(var_info,">, datatype in operator <</>>: ");
    strcat(var_info,buf2);
}


static inline void otl_strcpy(
unsigned char* trg,
unsigned char* src,
int& overflow,
const int inp_size=0
)
{
    unsigned char* c1=trg;
    unsigned char* c2=src;
    int out_size=0;
    overflow=0;
    while(*c2&&out_size<inp_size-1)
    {
        *c1=*c2;
        ++c1; ++c2;
        ++out_size;
    }
    *c1=0;
    if(*c2&&out_size==inp_size-1)
        overflow=1;
}


static inline void otl_itoa(int i,char* a)
{
    int n=i,k;
    char buf[64];
    char* c=buf;
    char *c1=a;
    char digit=' ';

    do
    {
        if(n>=10)
            k=n%10;
        else
            k=n;
        switch(k)
        {
            case 0: digit='0'; break;
            case 1: digit='1'; break;
            case 2: digit='2'; break;
            case 3: digit='3'; break;
            case 4: digit='4'; break;
            case 5: digit='5'; break;
            case 6: digit='6'; break;
            case 7: digit='8'; break;
            case 9: digit='9'; break;
            default: digit=' ';
        }
        *c=digit;
        ++c;
        n=n/10;
    }while(n!=0);
    *c=0;
    k=strlen(buf);
    for(int j=k-1;j>=0;--j)
    {
        *c1=buf[j];
        ++c1;
    }
    *c1=0;
}


static inline void otl_var_info_col
(const int pos,
const int ftype,
const int type_code,
char* var_info)
{
    char buf1[128];
    char buf2[128];
    char name[128];

    otl_itoa(pos,name);
    strcpy(buf1,otl_var_type_name(ftype));
    strcpy(buf2,otl_var_type_name(type_code));
    strcpy(var_info,"Column: ");
    strcat(var_info,name);
    strcat(var_info,"<");
    strcat(var_info,buf1);
    strcat(var_info,">, datatype in operator <</>>: ");
    strcat(var_info,buf2);
}


class otl_pl_tab_generic
{
    public:

        unsigned char* p_v;
        short* p_null;
        int elem_size;
        int tab_size;
        int tab_len;
        int vtype;

        otl_pl_tab_generic()
        {
            elem_size=0;
            tab_size=0;
            tab_len=0;
            p_v=0;
            p_null=0;
            vtype=0;
        }

        ~otl_pl_tab_generic(){}

        unsigned char* val(int ndx=0)
        {
            return p_v+(ndx*elem_size);
        }

        int is_null(int ndx=0)
        {
            return p_null[ndx]!=0;
        }

        void set_null(int ndx=0)
        {
            p_null[ndx]=1;
        }

        void set_non_null(int ndx=0)
        {
            p_null[ndx]=0;
        }

        void init_generic(void)
        {
            int i;
            memset(p_v,0,elem_size*tab_len);
            for(i=0;i<tab_len;++i)
                p_null[i]=0;
        }

        int len()
        {
            return tab_len;
        }

        void set_len(int new_len=0)
        {
            tab_len=new_len;
        }

};

static inline int otl_numeric_convert_int(
const int ftype,
const void* val,
int& n)
{
    int rc=1;
    switch(ftype)
    {
        case otl_var_double:
            n=(int)*(double*)val;
            break;
        case otl_var_short:
            n=(int)*(short*)val;
            break;
        case otl_var_int:
            n=(int)*(int*)val;
            break;
        case otl_var_unsigned_int:
            n=(int)*(unsigned int*)val;
            break;
        case otl_var_long_int:
            n=(int)*(long int*)val;
            break;
        case otl_var_float:
            n=(int)*(float*)val;
            break;
        default:
            rc=0;
            break;
    }
    return rc;
}


static inline int otl_numeric_convert_unsigned(
const int ftype,
const void* val,
unsigned& n)
{
    int rc=1;
    switch(ftype)
    {
        case otl_var_double:
            n=(unsigned)*(double*)val;
            break;
        case otl_var_short:
            n=(unsigned)*(short*)val;
            break;
        case otl_var_int:
            n=(unsigned)*(int*)val;
            break;
        case otl_var_unsigned_int:
            n=(unsigned)*(unsigned int*)val;
            break;
        case otl_var_long_int:
            n=(unsigned)*(long int*)val;
            break;
        case otl_var_float:
            n=(unsigned)*(float*)val;
            break;
        default:
            rc=0;
            break;
    }
    return rc;
}


static inline int otl_numeric_convert_short(
const int ftype,
const void* val,
short& n)
{
    int rc=1;
    switch(ftype)
    {
        case otl_var_double:
            n=(short)*(double*)val;
            break;
        case otl_var_short:
            n=(short)*(short*)val;
            break;
        case otl_var_int:
            n=(short)*(int*)val;
            break;
        case otl_var_unsigned_int:
            n=(short)*(unsigned int*)val;
            break;
        case otl_var_long_int:
            n=(short)*(long int*)val;
            break;
        case otl_var_float:
            n=(short)*(float*)val;
            break;
        default:
            rc=0;
            break;
    }
    return rc;
}


static inline int otl_numeric_convert_long_int(
const int ftype,
const void* val,
long int& n)
{
    int rc=1;
    switch(ftype)
    {
        case otl_var_double:
            n=(long int)*(double*)val;
            break;
        case otl_var_short:
            n=(long int)*(short*)val;
            break;
        case otl_var_int:
            n=(long int)*(int*)val;
            break;
        case otl_var_unsigned_int:
            n=(long int)*(unsigned int*)val;
            break;
        case otl_var_long_int:
            n=(long int)*(long int*)val;
            break;
        case otl_var_float:
            n=(long int)*(float*)val;
            break;
        default:
            rc=0;
            break;
    }
    return rc;
}


static inline int otl_numeric_convert_float(
const int ftype,
const void* val,
float& n)
{
    int rc=1;
    switch(ftype)
    {
        case otl_var_double:
            n=(float)*(double*)val;
            break;
        case otl_var_short:
            n=(float)*(short*)val;
            break;
        case otl_var_int:
            n=(float)*(int*)val;
            break;
        case otl_var_unsigned_int:
            n=(float)*(unsigned int*)val;
            break;
        case otl_var_long_int:
            n=(float)*(long int*)val;
            break;
        case otl_var_float:
            n=(float)*(float*)val;
            break;
        default:
            rc=0;
            break;
    }
    return rc;
}


static inline int otl_numeric_convert_double(
const int ftype,
const void* val,
double& n)
{
    int rc=1;
    switch(ftype)
    {
        case otl_var_double:
            n=(double)*(double*)val;
            break;
        case otl_var_short:
            n=(double)*(short*)val;
            break;
        case otl_var_int:
            n=(double)*(int*)val;
            break;
        case otl_var_unsigned_int:
            n=(double)*(unsigned int*)val;
            break;
        case otl_var_long_int:
            n=(double)*(long int*)val;
            break;
        case otl_var_float:
            n=(double)*(float*)val;
            break;
        default:
            rc=0;
            break;
    }
    return rc;
}


// =========================== COMMON TEMPLATES  ============================

template <class T>
class otl_auto_array_ptr
{
    public:

        T* ptr;

        otl_auto_array_ptr()
        {
            ptr=0;
        }

        otl_auto_array_ptr(const int arr_size)
        {
            ptr=new T[arr_size];
        }

        ~otl_auto_array_ptr()
        {
            delete[] ptr;
        }

};

template <class OTLStream,class OTLConnect>
class otl_tmpl_nocommit_stream: public OTLStream
{
    public:

        otl_tmpl_nocommit_stream(): OTLStream()
        {
            OTLStream::set_commit(0);
        }

        otl_tmpl_nocommit_stream
            (const short arr_size,
            const char* sqlstm,
            OTLConnect& db,
            const char* ref_cur_placeholder=0)
            : OTLStream(arr_size,sqlstm,db,ref_cur_placeholder)
        {
            OTLStream::set_commit(0);
        }

        void open
            (short int arr_size,
            const char* sqlstm,
            OTLConnect& db,
            const char* ref_cur_placeholder=0)
        {
            OTLStream::open(arr_size,sqlstm,db,ref_cur_placeholder);
            OTLStream::set_commit(0);
        }

};

template <class T,const int atab_size,const int avtype>
class otl_tmpl_pl_tab: public otl_pl_tab_generic
{
    public:
        T v[atab_size];
        short null_flag[atab_size];

        void init(void)
        {
            int i;
            tab_len=0;
            vtype=avtype;
            tab_size=atab_size;
            p_null=null_flag;
            p_v=(unsigned char*)v;
            elem_size=sizeof(T);
            for(i=0;i<atab_size;++i)
                null_flag[i]=0;
            memset(v,0,sizeof(v));
        }

        otl_tmpl_pl_tab()
        {
            init();
        }

        ~otl_tmpl_pl_tab(){}

};

template <const int atab_size>
class otl_int_tab: public otl_tmpl_pl_tab<int,atab_size,otl_var_int>
{
    public:
        otl_int_tab():otl_tmpl_pl_tab<int,atab_size,otl_var_int>(){}
};

template <const int atab_size>
class otl_double_tab: public otl_tmpl_pl_tab<double,atab_size,otl_var_double>
{
    public:
        otl_double_tab():otl_tmpl_pl_tab<double,atab_size,otl_var_double>(){}
};

template <const int atab_size>
class otl_float_tab: public otl_tmpl_pl_tab<float,atab_size,otl_var_float>
{
    public:
        otl_float_tab():otl_tmpl_pl_tab<float,atab_size,otl_var_float>(){}
};

template <const int atab_size>
class otl_unsigned_tab: public otl_tmpl_pl_tab<unsigned,atab_size,otl_var_unsigned_int>
{
    public:
        otl_unsigned_tab():otl_tmpl_pl_tab<unsigned,atab_size,otl_var_unsigned_int>(){}
};

template <const int atab_size>
class otl_short_tab: public otl_tmpl_pl_tab<short,atab_size,otl_var_short>
{
    public:
        otl_short_tab():otl_tmpl_pl_tab<short,atab_size,otl_var_short>(){}
};

template <const int atab_size>
class otl_long_int_tab: public otl_tmpl_pl_tab<long,atab_size,otl_var_long_int>
{
    public:
        otl_long_int_tab():otl_tmpl_pl_tab<long,atab_size,otl_var_long_int>(){}
};

template <const int atab_size,const int str_size>
class otl_cstr_tab: public otl_pl_tab_generic
{
    public:
        typedef unsigned char T[str_size];
        T v[atab_size];
        short null_flag[atab_size];

        void init(void)
        {
            int i;
            tab_len=0;
            vtype=otl_var_char;
            tab_size=atab_size;
            p_null=null_flag;
            p_v=(unsigned char*)v;
            elem_size=sizeof(T);
            for(i=0;i<atab_size;++i)
                null_flag[i]=0;
            memset(v,0,sizeof(v));
        }

        otl_cstr_tab()
        {
            init();
        }

        ~otl_cstr_tab(){}

};

template <const int atab_size>
class otl_datetime_tab: public otl_pl_tab_generic
{
    public:

        typedef otl_datetime T;

        T v[atab_size];
        short null_flag[atab_size];

        void init(void)
        {
            int i;
            tab_len=0;
            vtype=otl_var_timestamp;
            tab_size=atab_size;
            p_null=null_flag;
            p_v=(unsigned char*)v;
            elem_size=sizeof(otl_oracle_date);
            for(i=0;i<atab_size;++i)
                null_flag[i]=0;
        }

        otl_datetime_tab()
        {
            init();
        }

        ~otl_datetime_tab(){}

};

template <class T,const int avtype>
class otl_tmpl_dyn_pl_tab: public otl_pl_tab_generic
{
    public:
        T* v;
        short* null_flag;

        void init(const int atab_size=1)
        {
            int i;
            tab_len=0;
            vtype=avtype;
            tab_size=atab_size;
            v=new T[tab_size];
            null_flag=new short[tab_size];
            p_null=null_flag;
            p_v=(unsigned char*)v;
            elem_size=sizeof(T);
            for(i=0;i<atab_size;++i)
                null_flag[i]=0;
            memset(v,0,elem_size*tab_size);
        }

        otl_tmpl_dyn_pl_tab(const int atab_size=1)
        {
            v=0;
            null_flag=0;
            init(atab_size);
        }

        ~otl_tmpl_dyn_pl_tab()
        {
            delete[] v;
            delete[] null_flag;
        }

};

class otl_dynamic_int_tab: public otl_tmpl_dyn_pl_tab<int,otl_var_int>
{
    public:
        otl_dynamic_int_tab(const int atab_size=1)
            :otl_tmpl_dyn_pl_tab<int,otl_var_int>(atab_size){}
};

class otl_dynamic_double_tab: public otl_tmpl_dyn_pl_tab<double,otl_var_double>
{
    public:
        otl_dynamic_double_tab(const int atab_size=1)
            :otl_tmpl_dyn_pl_tab<double,otl_var_double>(atab_size){}
};

class otl_dynamic_float_tab: public otl_tmpl_dyn_pl_tab<float,otl_var_float>
{
    public:
        otl_dynamic_float_tab(const int atab_size=1)
            :otl_tmpl_dyn_pl_tab<float,otl_var_float>(atab_size){}
};

class otl_dynamic_unsigned_tab: public
otl_tmpl_dyn_pl_tab<unsigned,otl_var_unsigned_int>
{
    public:
        otl_dynamic_unsigned_tab(const int atab_size=1)
            :otl_tmpl_dyn_pl_tab<unsigned,otl_var_unsigned_int>(atab_size){}
};

class otl_dynamic_short_tab: public otl_tmpl_dyn_pl_tab<short,otl_var_short>
{
    public:
        otl_dynamic_short_tab(const int atab_size=1)
            :otl_tmpl_dyn_pl_tab<short,otl_var_short>(atab_size){}
};

class otl_dynamic_long_int_tab: public otl_tmpl_dyn_pl_tab<long,otl_var_long_int>
{
    public:
        otl_dynamic_long_int_tab(const int atab_size=1)
            :otl_tmpl_dyn_pl_tab<long,otl_var_long_int>(atab_size){}
};

template <const int str_size>
class otl_dynamic_cstr_tab: public otl_pl_tab_generic
{
    public:
        typedef unsigned char T[str_size];
        T* v;
        short* null_flag;

        void init(const int atab_size=1)
        {
            int i;
            tab_len=0;
            vtype=otl_var_char;
            tab_size=atab_size;
            v=new T[tab_size];
            null_flag=new short[tab_size];
            p_null=null_flag;
            p_v=(unsigned char*)v;
            elem_size=sizeof(T);
            for(i=0;i<atab_size;++i)
                null_flag[i]=0;
            memset(v,0,elem_size*tab_size);
        }

        otl_dynamic_cstr_tab(const int atab_size=1)
        {
            v=0;
            null_flag=0;
            init(atab_size);
        }

        ~otl_dynamic_cstr_tab()
        {
            delete[] v;
            delete[] null_flag;
        }

};

class otl_dynamic_datetime_tab: public otl_pl_tab_generic
{
    public:

        typedef otl_datetime T;

        T* v;
        short* null_flag;

        void init(const int atab_size=1)
        {
            int i;
            tab_len=0;
            vtype=otl_var_timestamp;
            tab_size=atab_size;
            v=new T[tab_size];
            null_flag=new short[tab_size];
            p_null=null_flag;
            p_v=(unsigned char*)v;
            elem_size=sizeof(otl_oracle_date);
            for(i=0;i<atab_size;++i)
                null_flag[i]=0;
        }

        otl_dynamic_datetime_tab(const int atab_size=1)
        {
            v=0;
            null_flag=0;
            init(atab_size);
        }

        ~otl_dynamic_datetime_tab()
        {
            delete[] v;
            delete[] null_flag;
        }

};

template <class TExceptionStruct,class TConnectStruct,class TCursorStruct>
class otl_tmpl_exception: public TExceptionStruct
{
    public:

        char stm_text[2048];
        char var_info[256];

        otl_tmpl_exception()
        {
            stm_text[0]=0;
            var_info[0]=0;
        }

        otl_tmpl_exception(TConnectStruct& conn_struct, const char* sqlstm=0)
        {
            stm_text[0]=0;
            var_info[0]=0;
            if(sqlstm)
            {
                strncpy((char*)stm_text,sqlstm,sizeof(stm_text));
                stm_text[sizeof(stm_text)-1]=0;
            }
            conn_struct.error((TExceptionStruct&)*this);
        }

        otl_tmpl_exception(TCursorStruct& cursor_struct, const char* sqlstm=0)
        {
            stm_text[0]=0;
            var_info[0]=0;
            if(sqlstm)
            {
                strncpy((char*)stm_text,sqlstm,sizeof(stm_text));
                stm_text[sizeof(stm_text)-1]=0;
            }
            cursor_struct.error((TExceptionStruct&)*this);
        }

        otl_tmpl_exception
            (const char* message,
            const int ex_code,
            const char* sqlstm=0,
            const char* varinfo=0)
        {
            stm_text[0]=0;
            var_info[0]=0;
            if(sqlstm)
            {
                strncpy((char*)stm_text,sqlstm,sizeof(stm_text));
                stm_text[sizeof(stm_text)-1]=0;
            }
            if(varinfo)strcpy((char*)var_info,varinfo);
            TExceptionStruct::init(message,ex_code);
        }

        ~otl_tmpl_exception(){}

};

template <class TExceptionStruct,class TConnectStruct,class TCursorStruct>
class otl_tmpl_connect
{
    protected:

    public:

        int connected;
        TConnectStruct connect_struct;
        int long_max_size;
        int retcode;

        void set_max_long_size(const int amax_size){long_max_size=amax_size;}
        int get_max_long_size(void){return long_max_size;}

        void set_timeout(const int atimeout=0)
        {
            connect_struct.set_timeout(atimeout);
        }

        void set_cursor_type(const int acursor_type=0)
        {
            connect_struct.set_cursor_type(acursor_type);
        }

        otl_tmpl_connect()
        {
            connected=0;
            long_max_size=32760;
            retcode=1;
        }

        otl_tmpl_connect(const char* connect_str,const int auto_commit=0)
        {
            connected=0;
            retcode=1;
            long_max_size=32760;
            rlogon(connect_str,auto_commit);
        }

        ~otl_tmpl_connect()
        {
            logoff();
        }

        static int otl_initialize(const int threaded_mode=0)
        {
            return TConnectStruct::initialize(threaded_mode);
        }

        void rlogon(const char* connect_str,const int auto_commit=0)
        {
            retcode=connect_struct.rlogon(connect_str,auto_commit);
            if(retcode)
                connected=1;
            else
            {
                connected=0;
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>(connect_struct);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
        }

        void logoff(void)
        {
            if (!connected) return;
            retcode=connect_struct.logoff();
            connected=0;
            if (retcode) return;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(connect_struct);
        }

        void commit(void)
        {
            if(!connected)return;
            retcode=connect_struct.commit();
            if(retcode)return;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(connect_struct);

        }

        void rollback(void)
        {
            if(!connected)return;
            retcode=connect_struct.rollback();
            if(retcode)return;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(connect_struct);
        }
};

template <class TVariableStruct>
class otl_tmpl_variable
{
    public:

        int param_type;
        int ftype;
        int elem_size;
        int array_size;
        char* name;
        int pos;
        int name_pos;
        int bound;

        int pl_tab_flag;

        TVariableStruct var_struct;

        int actual_elem_size(void)
        {
            return var_struct.actual_elem_size();
        }

        void copy_var_desc(otl_var_desc& v)
        {
            v.param_type=param_type;
            v.ftype=ftype;
            v.elem_size=elem_size;
            v.array_size=array_size;
            v.pos=pos;
            v.name_pos=name_pos;
            v.pl_tab_flag=pl_tab_flag;
        }

        otl_tmpl_variable()
        {
            name=0;
            pos=0;
            name_pos=0;
            pl_tab_flag=0;
            bound=0;
            param_type=OTL_INPUT_PARAM;
        }

        ~otl_tmpl_variable()
        {
            delete[] name;
        }

        otl_tmpl_variable
            (const int column_num,
            const int aftype,
            const int aelem_size,
            const short aarray_size)
        {
            copy_pos(column_num);
            init(aftype,aelem_size,aarray_size);
        }

        otl_tmpl_variable
            (const char* aname,
            const int aftype,
            const int aelem_size,
            const short aarray_size,
            const int apl_tab_flag=0)
        {
            copy_name(aname);
            init
                (aftype,
                aelem_size,
                aarray_size,
                0,
                apl_tab_flag);
        }

        void init
            (const int aftype,
            const int aelem_size,
            const short aarray_size,
            const void* connect_struct=0,
            const int apl_tab_flag=0)
        {
            ftype=aftype;
            elem_size=aelem_size;
            array_size=aarray_size;
            pl_tab_flag=apl_tab_flag;
            bound=0;
            var_struct.init(aftype,aelem_size,aarray_size,connect_struct,pl_tab_flag);
        }

        void set_param_type(const int aparam_type=OTL_INPUT_PARAM)
        {
            param_type=aparam_type;
        }

        int get_param_type(void)
        {
            return param_type;
        }

        void copy_name(const char* aname)
        {
            pos=0;
            if(name==aname)return;
            if(name)delete[] name;
            name=new char[strlen(aname)+1];
            strcpy(name,aname);
        }

        void copy_pos(const int apos)
        {
            if(name)
            {
                delete[] name;
                name=0;
                name_pos=0;
            }
            pos=apos;
        }

        void set_null(int ndx)
        {
            var_struct.set_null(ndx);
        }

        void set_not_null(int ndx)
        {
            var_struct.set_not_null(ndx,elem_size);
        }

        void set_len(int len, int ndx=0)
        {
            var_struct.set_len(len,ndx);
        }

        int get_len(int ndx=0)
        {
            return var_struct.get_len(ndx);
        }

        int get_pl_tab_len(void)
        {
            return var_struct.get_pl_tab_len();
        }

        int get_max_pl_tab_len(void)
        {
            return var_struct.get_max_pl_tab_len();
        }

        void set_pl_tab_len(const int pl_tab_len)
        {
            var_struct.set_pl_tab_len(pl_tab_len);
        }

        int is_null(int ndx)
        {
            return var_struct.is_null(ndx);
        }

        void* val(int ndx=0)
        {
            return var_struct.val(ndx,elem_size);
        }

        static void map_ftype
            (otl_column_desc& desc,
            const int max_long_size,
            int& ftype,
            int& elem_size,
            otl_select_struct_override& override,
            const int column_ndx)
        {
            TVariableStruct::map_ftype(desc,max_long_size,ftype,elem_size,override,column_ndx);
        }

};

template <class TExceptionStruct,
class TConnectStruct,
class TCursorStruct,
class TVariableStruct>
class otl_tmpl_cursor
{
    public:

        int connected;
        char* stm_text;
        TCursorStruct cursor_struct;
        int vl_len;
        otl_tmpl_variable<TVariableStruct>** vl;
        otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>* adb;
        int eof_data;
        int eof_desc;
        int retcode;
        long _rpc;

        otl_tmpl_cursor()
        {
            connected=0;
            stm_text=0;
            vl_len=0;
            vl=0;
            eof_data=0;
            eof_desc=0;
            adb=0;
            _rpc=0;
            retcode=1;
        }

        otl_tmpl_cursor
            (otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& connect)
        {
            connected=0;
            stm_text=0;
            vl_len=0;
            vl=0;
            eof_data=0;
            eof_desc=0;
            retcode=1;
            _rpc=0;
            adb=&connect;
            open(connect);
        }

        virtual ~otl_tmpl_cursor()
        {
            close();
            delete[] stm_text;
            stm_text=0;
        }

        void open
            (otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& connect)
        {
            eof_data=0;
            eof_desc=0;
            retcode=1;
            adb=&connect;
            _rpc=0;
            retcode=cursor_struct.open(connect.connect_struct);
            if(retcode)
            {
                connected=1;
                return;
            }
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(cursor_struct);
        }

        virtual void close(void)
        {
            _rpc=0;
            if(!connected)return;
            if(adb)
            {
                if(!adb->connected)
                {
                    connected=0;
                    adb=0;
                    retcode=1;
                    return;
                }
            }
            connected=0;
            adb=0;
            retcode=cursor_struct.close();
            if(retcode)return;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(cursor_struct);
        }

        void parse(void)
        {
            _rpc=0;
            if(!connected)return;
            retcode=cursor_struct.parse(stm_text);
            if(retcode)return;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(cursor_struct,stm_text);
        }

        void parse(const char* sqlstm)
        {
            if(!connected)return;
            if(stm_text)
            {
                delete[] stm_text;
                stm_text=0;
            }
            stm_text=new char[strlen(sqlstm)+1];
            strcpy(stm_text,sqlstm);
            parse();
        }

        long get_rpc()
        {
            return _rpc;
        }

        void exec(const int iters=1)
        {
            if(!connected)return;
            retcode=cursor_struct.exec(iters);
            _rpc=cursor_struct.get_rpc();
            if(retcode)return;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(cursor_struct,stm_text);
        }

        virtual void bind
            (const char* name,
            otl_tmpl_variable<TVariableStruct>& v)
        {
            if(!connected)return;
            if(v.bound)return;
            v.copy_name(name);
            retcode=cursor_struct.bind
                (name,
                v.var_struct,
                v.elem_size,
                v.ftype,
                v.param_type,
                v.name_pos,
                v.pl_tab_flag);
            if(retcode)
            {
                v.bound=1;
                return;
            }
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(cursor_struct,stm_text);
        }

        virtual void bind
            (const int column_num,
            otl_tmpl_variable<TVariableStruct>& v)
        {
            if(!connected)return;
            v.copy_pos(column_num);
            retcode=cursor_struct.bind
                (column_num,
                v.var_struct,
                v.elem_size,
                v.ftype,
                v.param_type);
            if(retcode)return;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(cursor_struct,stm_text);
        }

        virtual void bind(otl_tmpl_variable<TVariableStruct>& v)
        {
            if(!connected)return;
            if(v.name) bind(v.name,v);
            if(v.pos) bind(v.pos,v);
        }

        static long direct_exec
            (otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& connect,
            const char* sqlstm,
            const int exception_enabled=1)
        {
            try
            {
                otl_tmpl_cursor
                    <TExceptionStruct,TConnectStruct,
                    TCursorStruct,TVariableStruct> cur(connect);
                cur.cursor_struct.set_direct_exec(1);
                cur.parse(sqlstm);
                cur.exec();
                return cur.cursor_struct.get_rpc();
            }catch(otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>)
            {
                if(exception_enabled)
                    throw;
            }
            return -1;
        }

        virtual int eof(void){return eof_data;}

        int describe_column
            (otl_column_desc& col,
            const int column_num)
        {
            if(!connected)return 0;
            retcode=cursor_struct.describe_column
                (col,column_num,eof_desc);
            if(eof_desc)return 0;
            if(retcode)return 1;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(cursor_struct,stm_text);
        #ifndef __SUNPRO_CC
            return 0;
        #endif
        }

};

//extern "C" int atoi(const char*);

static inline char otl_to_upper(char c)
{
    return (char)toupper(c);
}


template <class TVariableStruct,
class TTimestampStruct,
class TExceptionStruct,
class TConnectStruct,
class TCursorStruct>
class otl_tmpl_ext_hv_decl
{
    public:

        enum var_status
        {
            in=0,
            out=1,
            io=2,
            def=3
        };

        char* hv[otl_var_list_size];
        short inout[otl_var_list_size];
        int pl_tab_size[otl_var_list_size];
        int array_size;
        short vst[4];
        int len;

        otl_tmpl_ext_hv_decl(char* stm,int arr_size=1)
        {
            int j;
            array_size=arr_size;

            int i=0;
            short in_str=0;
            char *c=stm;

            hv[i]=0;
            while(*c)
            {
                if(*c=='\'')
                {
                    if(!in_str)
                        in_str=1;
                    else
                    {
                        if(c[1]=='\'')
                            ++c;
                        else
                            in_str=0;
                    }
                }
                if(*c==':'&&!in_str)
                {
                    short in_out=def;
                    int apl_tab_size=0;
                    char var[64];
                    char* v=var;
                    *v++=*c++;
                    while(is_id(*c))
                        *v++=*c++;
                    while(isspace(*c)&&*c)
                        ++c;
                    if(*c=='<')
                    {
                        *c=' ';
                        while(*c!='>'&&*c!=','&&*c)
                        {
                            *v++=*c;
                            *c++=' ';
                        }
                        if(*c==',')
                        {
                            *c++=' ';
                            if(otl_to_upper(*c)=='I')
                            {
                                if(otl_to_upper(c[2])=='O')
                                    in_out=io;
                                else
                                    in_out=in;
                            }else if(otl_to_upper(*c)=='O')
                            in_out=out;
                            while(*c!='>'&&*c&&*c!='[')
                                *c++=' ';
                            if(*c=='[')
                            {
                                char tmp[32];
                                char *t=tmp;
                                *c++=' ';
                                while(*c!=']'&&*c!='>'&&*c)
                                {
                                    *t++=*c;
                                    *c++=' ';
                                }
                                *t='\0';
                                apl_tab_size=atoi(tmp);
                                while(*c!='>'&&*c)
                                    *c++=' ';
                            }
                        }
                        *c=' ';
                        *v='\0';
                        add_var(i,var,in_out,apl_tab_size);
                    }
                }
                ++c;
            }

            for(j=0;j<4;++j)vst[j]=0;
            i=0;
            while(hv[i])
            {
                switch(inout[i])
                {
                    case in:
                        ++vst[0];
                        break;
                    case out:
                        ++vst[1];
                        break;
                    case io:
                        ++vst[2];
                        break;
                    case def:
                        ++vst[3];
                        break;
                }
                ++i;
            }
            len=i;
        }

        ~otl_tmpl_ext_hv_decl()
        {
            int i;
            for(i=0;hv[i]!=0;++i)
                delete[] hv[i];
        }

        char* operator[](int ndx){return hv[ndx];}
        short v_status(int ndx){return inout[ndx];}
        int is_id(char c){return isalnum(c)||c=='_';}

        int name_comp(char* n1,char* n2)
        {
            while(*n1!=' '&&*n1!='\0'&&*n2!=' '&&*n2!='\0')
            {
                if(otl_to_upper(*n1)!=otl_to_upper(*n2))return 0;
                ++n1;
                ++n2;
            }
            if(*n1==' '&&*n2!=' '||*n2==' '&&*n1!=' ')
                return 0;
            return 1;
        }

        void add_var(int &n,char* v,short in_out,int apl_tab_size=0)
        {
            int i;
            for(i=0;i<n;++i)
                if(name_comp(hv[i],v))
                    return;
            hv[n]=new char[strlen(v)+1];
            strcpy(hv[n],v);
            inout[n]=in_out;
            pl_tab_size[n]=apl_tab_size;
            hv[++n]=0;
            inout[n]=def;
            pl_tab_size[n]=0;
        }

        otl_tmpl_variable<TVariableStruct>* alloc_var
            (char* s,
            const int vstat,
            const int status,
            otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db,
            const int apl_tab_size=0)
        {
            char name[128];
            char type;
            char t2;
            char t3;
            int size=0;

            char *c=name,*c1=s;
            while(*c1!=' '&&*c1)
                *c++=*c1++;
            *c='\0';
            while(*c1==' '&&*c1)
                ++c1;
            type=otl_to_upper(c1[0]);
            t2=otl_to_upper(c1[1]);
            t3=otl_to_upper(c1[2]);
            if(type=='C'&&t2=='H')
            {
                char tmp[32];
                char *t=tmp;
                while(*c1!='['&&*c1)
                    ++c1;
                ++c1;
                while(*c1!=']'&&*c1)
                    *t++=*c1++;
                *t='\0';
                size=atoi(tmp);
            }

            if(status==in && (vstat==in||vstat==io))
                ;
            else if(status==out && (vstat==out||vstat==io||vstat==def))
                ;
            else if(status==def)
                ;
            else
                return 0;

            int pl_tab_flag=0;

            if(apl_tab_size)
            {
                array_size=apl_tab_size;
                pl_tab_flag=1;
            }

            otl_tmpl_variable<TVariableStruct>* v=
                new otl_tmpl_variable<TVariableStruct>;
            v->copy_name(name);
            switch(type)
            {
                case 'B':
                    v->init(otl_var_blob,db.get_max_long_size(),
                        array_size,&db.connect_struct);
                    break;
                case 'C':
                    if(t2=='H')
                        v->init(otl_var_char,size,array_size,&db.connect_struct,pl_tab_flag);
                    else if(t2=='L')
                        v->init(otl_var_clob,db.get_max_long_size(),
                                array_size,&db.connect_struct);
                    else
                    {
                        delete v;
                        v=0;
                    }
                    break;
                case 'D':
                    v->init(otl_var_double,sizeof(double),array_size,&db.connect_struct,pl_tab_flag);
                    break;
                case 'F':
                    v->init(otl_var_float,sizeof(float),array_size,&db.connect_struct,pl_tab_flag);
                    break;
                case 'I':
                    v->init(otl_var_int,sizeof(int),array_size,&db.connect_struct,pl_tab_flag);
                    break;
                case 'U':
                    v->init(otl_var_unsigned_int,sizeof(unsigned),
                        array_size,&db.connect_struct,pl_tab_flag);
                    break;
                case 'S':
                    v->init(otl_var_short,sizeof(short),
                        array_size,&db.connect_struct,pl_tab_flag);
                    break;
                case 'L':
                    if(t2=='O'&&t3=='N')
                        v->init(otl_var_long_int,sizeof(long),
                            array_size,&db.connect_struct,pl_tab_flag);
                    else
                    {
                        delete v;
                        v=0;
                    }
                    break;
                case 'T':
                    v->init(otl_var_timestamp,sizeof(TTimestampStruct),
                        array_size,&db.connect_struct,pl_tab_flag);
                    break;
                case 'V':
                    v->init(otl_var_varchar_long,db.get_max_long_size(),
                        array_size,&db.connect_struct);
                    break;
                case 'R':
                    v->init(otl_var_raw_long,db.get_max_long_size(),
                        array_size,&db.connect_struct);
                    break;
                default:
                    delete v;
                    v=0;
                    break;
            }
            return v;
        }

        void alloc_host_var_list
            (otl_tmpl_variable<TVariableStruct>** &vl,
            int& vl_len,
            otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db,
            const int status=def)
        {
            int j;
            vl_len=0;
            if(!hv[0])
            {
                vl=0;
                return;
            }
            otl_tmpl_variable<TVariableStruct>* tmp_vl[otl_var_list_size];
            int i=0;
            while(hv[i])
            {
                otl_tmpl_variable<TVariableStruct>* vp=alloc_var
                    (hv[i],inout[i],status,db,pl_tab_size[i]);
                vp->name_pos=i+1;
                if(vp)
                {
                    ++vl_len;
                    tmp_vl[vl_len-1]=vp;
                }
                ++i;
            }
            if(vl_len>0)
            {
                vl=new otl_tmpl_variable<TVariableStruct>*[vl_len];
                for(j=0;j<vl_len;++j)
                    vl[j]=tmp_vl[j];
            }
        }

};

template <class TExceptionStruct,
class TConnectStruct,
class TCursorStruct,
class TVariableStruct,
class TSelectCursorStruct>
class otl_tmpl_select_cursor:
public otl_tmpl_cursor
<TExceptionStruct,TConnectStruct,TCursorStruct,TVariableStruct>
{
    public:

        int cur_row;
        int cur_size;
        int row_count;
        int array_size;

        TSelectCursorStruct select_cursor_struct;

        otl_tmpl_select_cursor
            (otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db,
            const short arr_size=1)
            : otl_tmpl_cursor
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>(db)
        {
            cur_row=-1;
            row_count=0;
            cur_size=0;
            array_size=arr_size;
            select_cursor_struct.init(array_size);
        }

        otl_tmpl_select_cursor()
            : otl_tmpl_cursor
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>(){}

        void open
            (otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db,
            short arr_size=1)
        {
            cur_row=-1;
            row_count=0;
            cur_size=0;
            array_size=arr_size;
            otl_tmpl_cursor
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct,
                TVariableStruct>::open(db);
        }

        void close(void)
        {
            otl_tmpl_cursor
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct,
                TVariableStruct>::close();
        }

        int first(void)
        {
            if(!otl_tmpl_cursor<TExceptionStruct,
                TConnectStruct,
                TCursorStruct,
                TVariableStruct>::connected)return 0;
            int rc=select_cursor_struct.first
                (otl_tmpl_cursor<TExceptionStruct,TConnectStruct,
                TCursorStruct,TVariableStruct>::cursor_struct,
                cur_row,cur_size,
                row_count,
                otl_tmpl_cursor<TExceptionStruct,TConnectStruct,
                TCursorStruct,TVariableStruct>::eof_data,
                array_size);
            if(!rc)
            {
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>(otl_tmpl_cursor<TExceptionStruct,TConnectStruct,
                    TCursorStruct,TVariableStruct>::cursor_struct,
                    otl_tmpl_cursor<TExceptionStruct,TConnectStruct,
                    TCursorStruct,TVariableStruct>::stm_text);
            #ifndef __SUNPRO_CC
                return 0;
            #endif
            }
            return cur_size!=0;
        }

        int next(void)
        {
            if(!otl_tmpl_cursor
                <TExceptionStruct,TConnectStruct,
                TCursorStruct,TVariableStruct>::connected)return 0;
            if(cur_row==-1)return first();
            int rc=select_cursor_struct.next
                (otl_tmpl_cursor
                <TExceptionStruct,TConnectStruct,
                TCursorStruct,TVariableStruct>::cursor_struct,
                cur_row,cur_size,
                row_count,
                otl_tmpl_cursor
                <TExceptionStruct,TConnectStruct,
                TCursorStruct,TVariableStruct>::eof_data,
                array_size);
            if(!rc)
            {
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>(otl_tmpl_cursor
                    <TExceptionStruct,TConnectStruct,
                    TCursorStruct,TVariableStruct>::cursor_struct,
                    otl_tmpl_cursor
                    <TExceptionStruct,TConnectStruct,
                    TCursorStruct,TVariableStruct>::stm_text);
            #ifndef __SUNPRO_CC
                return 0;
            #endif
            }
            return cur_size!=0;
        }

};

const int otl_lob_stream_read_mode=1;
const int otl_lob_stream_write_mode=2;
const int otl_lob_stream_zero_mode=3;

const int otl_lob_stream_first_piece=1;
const int otl_lob_stream_next_piece=2;
const int otl_lob_stream_last_piece=3;

template <class TExceptionStruct,
class TConnectStruct,
class TCursorStruct,
class TVariableStruct>
class otl_tmpl_lob_stream
{
    public:

        otl_tmpl_variable<TVariableStruct>* bind_var;
        otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>* connect;

        otl_tmpl_cursor
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>* cursor;

        int mode;
        int retcode;
        int ndx;
        int offset;
        int lob_len;
        int in_destructor;
        int eof_flag;

        void init
            (otl_tmpl_variable<TVariableStruct>* avar,
            otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>* aconnect,
            otl_tmpl_cursor
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>* acursor,
            int andx,
            int amode)
        {
            connect=aconnect;
            bind_var=avar;
            cursor=acursor;
            mode=amode;
            retcode=0;
            ndx=andx;
            offset=0;
            lob_len=0;
            eof_flag=0;
            in_destructor=0;
            if(bind_var)
                bind_var->var_struct.set_lob_stream_flag();
        }

        void set_len(const int new_len=0)
        {
            lob_len=new_len;
        }

        otl_tmpl_lob_stream()
        {
            init(0,0,0,0,otl_lob_stream_zero_mode);
        }

        ~otl_tmpl_lob_stream()
        {
            in_destructor=1;
            close();
        }

        otl_tmpl_lob_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct>& operator<<(const otl_long_string& s)
        {
            if(mode!=otl_lob_stream_write_mode)
            {
                char* stm=0;
                char var_info[256];
                var_info[0]=0;
                if(cursor!=0)stm=cursor->stm_text;
                if(bind_var!=0)
                {
                    otl_var_info_var
                        (bind_var->name,
                        bind_var->ftype,
                        otl_var_long_string,
                        var_info);
                }
                char* vinfo=0;
                if(var_info[0]!=0)
                    vinfo=&var_info[0];
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_9,
                    otl_error_code_9,
                    stm,
                    vinfo);
            #ifndef __SUNPRO_CC
                return *this;
            #endif
            }
            if(offset==0)offset=1;
            if((offset-1)+s.length>lob_len)
            {
                char var_info[256];
                otl_var_info_var
                    (bind_var->name,
                    bind_var->ftype,
                    otl_var_long_string,
                    var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_7,
                    otl_error_code_7,
                    cursor->stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return *this;
            #endif
            }
            retcode=bind_var->var_struct.write_blob(s,lob_len,offset);
            if(retcode)
            {
                if((offset-1)==lob_len)
                    close();
                return *this;
            }
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(connect->connect_struct,cursor->stm_text);
        #ifndef __SUNPRO_CC
            return *this;
        #endif
        }

        otl_tmpl_lob_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct>& operator>>(otl_long_string& s)
        {
            if(mode!=otl_lob_stream_read_mode)
            {
                char* stm=0;
                char var_info[256];
                var_info[0]=0;
                if(cursor!=0)stm=cursor->stm_text;
                if(bind_var!=0)
                {
                    otl_var_info_var
                        (bind_var->name,
                        bind_var->ftype,
                        otl_var_long_string,
                        var_info);
                }
                char* vinfo=0;
                if(var_info[0]!=0)
                    vinfo=&var_info[0];
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_10,
                    otl_error_code_10,
                    stm,
                    vinfo);
            #ifndef __SUNPRO_CC
                return *this;
            #endif
            }
            if(offset==0&&lob_len==0)
                lob_len=len();
            if(lob_len==0||(offset-1)==lob_len)
            {
                s.set_len(0);
                eof_flag=1;
                return *this;
            }
            if(offset==0)offset=1;
            retcode=bind_var->var_struct.read_blob(s,ndx,offset,lob_len);
            if((offset-1)==lob_len)eof_flag=1;
            if(retcode)
            {
                if(eof())
                {
                    close();
                    eof_flag=1;
                }
                return *this;
            }
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(connect->connect_struct,cursor->stm_text);
        #ifndef __SUNPRO_CC
            return *this;
        #endif
        }

        int eof(void)
        {
            return eof_flag;
        }

        int len(void)
        {
            if(cursor==0||connect==0||bind_var==0)return 0;
            int alen;
            retcode=bind_var->var_struct.get_blob_len(ndx,alen);
            if(retcode)return alen;
            throw otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>(connect->connect_struct,cursor->stm_text);
        #ifndef __SUNPRO_CC
            return 0;
        #endif
        }

        void close(void)
        {
            if(in_destructor)
            {
                if(mode==otl_lob_stream_read_mode)
                {
                    bind_var->var_struct.set_lob_stream_flag(0);
                    bind_var->set_not_null(0);
                }
                return;
            }
            if(mode==otl_lob_stream_zero_mode)return;
            if(mode==otl_lob_stream_read_mode)
            {
                bind_var->var_struct.set_lob_stream_flag(0);
                bind_var->set_not_null(0);
                init(0,0,0,0,otl_lob_stream_zero_mode);
            }
            else
            {
                // write mode
                if(!(offset==0&&lob_len==0)&&(offset-1)!=lob_len)
                {
                    char var_info[256];
                    char msg_buf[1024];
                    strcpy(msg_buf,otl_error_msg_8);
                    otl_var_info_var
                        (bind_var->name,
                        bind_var->ftype,
                        otl_var_long_string,
                        var_info);
                    throw otl_tmpl_exception
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct>
                        (msg_buf,
                        otl_error_code_8,
                        cursor->stm_text,
                        var_info);
                }
                bind_var->var_struct.set_lob_stream_flag(0);
                bind_var->set_not_null(0);
            }
        }

};

template <class TExceptionStruct,
class TConnectStruct,
class TCursorStruct,
class TVariableStruct,
class TSelectCursorStruct,
class TTimestampStruct>
class otl_tmpl_select_stream: public otl_tmpl_select_cursor
<TExceptionStruct,TConnectStruct,TCursorStruct,
TVariableStruct,TSelectCursorStruct>
{
    public:

        otl_column_desc* sl_desc;
        otl_tmpl_variable<TVariableStruct>* sl;
        int sl_len;
        int null_fetched;
        int cur_col;
        int cur_in;
        int executed;
        int eof_status;
        char var_info[256];
        otl_select_struct_override* override;

        void cleanup(void)
        {
            int i;
            delete[] sl;
            for(i=0;
                i < otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>::vl_len;
                ++i)
            delete otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::vl[i];
            delete[] otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>::vl;
            delete[] sl_desc;
        }

        ~otl_tmpl_select_stream()
        {
            cleanup();
        }

        otl_tmpl_select_stream
            (otl_select_struct_override* aoverride,
            const short arr_size,
            const char* sqlstm,
            otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db,
            const int implicit_select=otl_explicit_select)
            : otl_tmpl_select_cursor
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct>(db,arr_size)
        {
            int i;
            otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>::select_cursor_struct.set_select_type
                (implicit_select);
            sl=0;
            sl_len=0;
            null_fetched=0;
            otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>::retcode=0;
            sl_desc=0;
            executed=0;
            cur_in=0;
            otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>::stm_text=0;
            eof_status=1;
            override=aoverride;

            {
                int len=strlen(sqlstm)+1;
                otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::stm_text=new char[len];
                strcpy(otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::stm_text,
                    sqlstm);
                otl_tmpl_ext_hv_decl
                    <TVariableStruct,TTimestampStruct,TExceptionStruct,
                    TConnectStruct,TCursorStruct> hvd
                    (otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::stm_text,1);
                hvd.alloc_host_var_list
                    (otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::vl,
                    otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::vl_len,
                    db
                    );
            }

            try
            {
                otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::parse();
                if(!otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>
                    ::select_cursor_struct.implicit_cursor)
                {
                    get_select_list();
                    bind_all();
                }
                else
                {
                    for(i=0;
                        i < otl_tmpl_select_cursor
                        <TExceptionStruct,TConnectStruct,TCursorStruct,
                        TVariableStruct,TSelectCursorStruct>::vl_len;
                        ++i)
                    bind(*otl_tmpl_select_cursor
                            <TExceptionStruct,TConnectStruct,TCursorStruct,
                            TVariableStruct,TSelectCursorStruct>::vl[i]);
                }
                if(otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::vl_len==0)
                {
                    rewind();
                    null_fetched=0;
                }
            }catch(otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>)
            {
                cleanup();
                throw;
            }

        }

        void rewind(void)
        {
            int i;
            if(otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>
                ::select_cursor_struct.implicit_cursor)
            {
                otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::exec(1);
                if(sl)
                {
                    delete[] sl;
                    sl=0;
                }
                get_select_list();
                for(i=0;i<sl_len;++i)bind(sl[i]);
            }
            eof_status=otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>::first();
            null_fetched=0;
            cur_col=-1;
            cur_in=0;
            executed=1;
        }

        int is_null(void)
        {
            return null_fetched;
        }

        int eof(void)
        {
            return !eof_status;
        }

        void bind_all(void)
        {
            int i;
            for(i=0;
                i < otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>::vl_len;
                ++i)
            bind(*otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::vl[i]
                    );
            for(i=0;i<sl_len;++i)bind(sl[i]);
        }

        void get_select_list(void)
        {
            int j;

            otl_auto_array_ptr<otl_column_desc> loc_ptr(otl_var_list_size);
            otl_column_desc* sl_desc_tmp=loc_ptr.ptr;
            int sld_tmp_len=0;
            int ftype,elem_size,i;

            for(i=1;
                otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>
                ::describe_column(sl_desc_tmp[i-1],i);
                ++i)
            ++sld_tmp_len;
            sl_len=sld_tmp_len;
            if(sl)
            {
                delete[] sl;
                sl=0;
            }
            sl=new otl_tmpl_variable<TVariableStruct>[sl_len];
            int max_long_size=otl_tmpl_select_cursor
                <TExceptionStruct,TConnectStruct,TCursorStruct,
                TVariableStruct,TSelectCursorStruct>
                ::adb->get_max_long_size();
            for(j=0;j<sl_len;++j)
            {
                otl_tmpl_variable<TVariableStruct>::map_ftype
                    (sl_desc_tmp[j],max_long_size,ftype,elem_size,*override,j+1);
                sl[j].copy_pos(j+1);
                sl[j].init(ftype,
                    elem_size,
                    (short)otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>
                    ::array_size,
                    &otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>
                    ::adb->connect_struct
                    );
            }
            if(sl_desc)
            {
                delete[] sl_desc;
                sl_desc=0;
            }
            sl_desc=new otl_column_desc[sl_len];
            memcpy(sl_desc,sl_desc_tmp,sizeof(otl_column_desc)*sl_len);
        }

        void check_if_executed(void)
        {
            if(!executed)
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_2,
                    otl_error_code_2,
                    otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::stm_text,
                    0);
        }

        int check_type(int type_code,int actual_data_type=0)
        {
            int out_type_code;
            if(actual_data_type!=0)
                out_type_code=actual_data_type;
            else
                out_type_code=type_code;
            if(sl[cur_col].ftype!=type_code)
            {
                otl_var_info_col
                    (sl[cur_col].pos,
                    sl[cur_col].ftype,
                    out_type_code,
                    var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return 0;
            #endif
            }else
            return 1;
        }

        void get_next(void)
        {
            if(cur_col<sl_len-1)
            {
                ++cur_col;
                null_fetched=sl[cur_col].is_null
                    (otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::cur_row);
            }
            else
            {
                eof_status=otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::next();
                cur_col=0;
            }
        }

        void look_ahead(void)
        {
            if(cur_col==sl_len-1)
            {
                eof_status=otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::next();
                cur_col=-1;
            }
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(char& c)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                c=*(char*)sl[cur_col].val
                    (otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::cur_row);
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(unsigned char& c)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                c=*(unsigned char*)sl[cur_col].val
                    (otl_tmpl_select_cursor
                    <TExceptionStruct,TConnectStruct,TCursorStruct,
                    TVariableStruct,TSelectCursorStruct>::cur_row);
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(char* s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                strcpy((char*)s,(char*)sl[cur_col].val(this->cur_row));
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(unsigned char* s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                strcpy((char*)s,(char*)sl[cur_col].val(this->cur_row));
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(int& n)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_int
                    (sl[cur_col].ftype,
                    sl[cur_col].val(this->cur_row),
                    n);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_int))
                        n=(int)*(double*)sl[cur_col].val(this->cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(unsigned& u)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_unsigned
                    (sl[cur_col].ftype,
                    sl[cur_col].val(this->cur_row),
                    u);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_unsigned_int))
                        u=(unsigned)*(double*)sl[cur_col].val(this->cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(short& sh)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_short
                    (sl[cur_col].ftype,
                    sl[cur_col].val(this->cur_row),
                    sh);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_short))
                        sh=(short)*(double*)sl[cur_col].val(this->cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(long int& l)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_long_int
                    (sl[cur_col].ftype,
                    sl[cur_col].val(this->cur_row),
                    l);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_long_int))
                        l=(long int)*(double*)sl[cur_col].val(this->cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(float& f)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_float
                    (sl[cur_col].ftype,
                    sl[cur_col].val(this->cur_row),
                    f);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_float))
                        f=(float)*(double*)sl[cur_col].val(this->cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(double& d)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_double
                    (sl[cur_col].ftype,
                    sl[cur_col].val(this->cur_row),
                    d);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_double))
                        d=*(double*)sl[cur_col].val(this->cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(TTimestampStruct& t)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_timestamp)&&!eof())
            {
                TTimestampStruct* tm=(TTimestampStruct*)sl[cur_col].val(this->cur_row);
                memcpy((void*)&t,tm,sizeof(TTimestampStruct));
                look_ahead();
            }
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>(otl_long_string& s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if((sl[cur_col].ftype==otl_var_varchar_long||
                sl[cur_col].ftype==otl_var_raw_long)&&
                !eof())
            {
                unsigned char* c=(unsigned char*)sl[cur_col].val(this->cur_row);
                int len=sl[cur_col].get_len(this->cur_row);
                if(len>s.buf_size)len=s.buf_size;
                memcpy(s.v,c,len);
                s.v[len]=0;
                s.set_len(len);
                look_ahead();
            }else if((sl[cur_col].ftype==otl_var_blob||
                sl[cur_col].ftype==otl_var_clob)&&
                !eof())
            {
                int len=0;
                int rc=sl[cur_col].var_struct.get_blob(this->cur_row,s.v,s.buf_size,len);
                if(rc==0)
                    throw otl_tmpl_exception
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct>(this->adb->connect_struct,this->stm_text);
                if(len>s.buf_size)len=s.buf_size;
                s.set_len(len);
                s.v[len]=0;
                look_ahead();
            }
            else
            {
                char l_var_info[256];
                otl_var_info_col
                    (sl[cur_col].pos,
                    sl[cur_col].ftype,
                    otl_var_long_string,
                    l_var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    this->stm_text,
                    l_var_info);
            }
            return *this;
        }

    #ifdef OTL_ORA8
        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator>>
            (otl_tmpl_lob_stream
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>& s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if((sl[cur_col].ftype==otl_var_blob||
                sl[cur_col].ftype==otl_var_clob)&&
                !eof())
            {
                s.init
                    (&sl[cur_col],
                    this->adb,
                    (otl_tmpl_cursor
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct,
                    TVariableStruct>*)this,
                    this->cur_row,
                    otl_lob_stream_read_mode);
                look_ahead();
            }
            else
            {
                char l_var_info[256];
                otl_var_info_col
                    (sl[cur_col].pos,
                    sl[cur_col].ftype,
                    otl_var_long_string,
                    l_var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    this->stm_text,
                    l_var_info);
            }
            return *this;
        }
    #endif

        int check_in_type(int type_code,int tsize)
        {
            if(this->vl[cur_in]->ftype==otl_var_char&&type_code==otl_var_char)
                return 1;
            if(this->vl[cur_in]->ftype!=type_code||this->vl[cur_in]->elem_size!=tsize)
            {
                otl_var_info_var
                    (this->vl[cur_in]->name,
                    this->vl[cur_in]->ftype,
                    type_code,
                    var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    this->stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return 1;
            #endif
            }else
            return 1;
        }

        void check_in_var(void)
        {
            if(this->vl_len==0)
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_1,
                    otl_error_code_1,
                    this->stm_text,
                    0);
        }

        void get_in_next(void)
        {
            if(cur_in==this->vl_len-1)
                rewind();
            else
            {
                ++cur_in;
                executed=0;
            }
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const otl_null n)
        {
            OTL_UNUSED_ARG(n)
                check_in_var();
            this->vl[cur_in]->set_null(0);
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const char c)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {
                char* tmp=(char*)this->vl[cur_in]->val();
                tmp[0]=c;
                tmp[1]=0;
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const unsigned char c)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {
                unsigned char* tmp=(unsigned char*)this->vl[cur_in]->val();
                tmp[0]=c;
                tmp[1]=0;
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const char* s)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {

                int overflow;
                otl_strcpy
                    ((unsigned char*)this->vl[cur_in]->val(),
                    (unsigned char*)s,
                    overflow,
                    this->vl[cur_in]->elem_size
                    );
                if(overflow)
                {
                    char l_var_info[256];
                    otl_var_info_var
                        (this->vl[cur_in]->name,
                        this->vl[cur_in]->ftype,
                        otl_var_char,
                        l_var_info);
                    throw otl_tmpl_exception
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct>
                        (otl_error_msg_4,
                        otl_error_code_4,
                        this->stm_text,
                        l_var_info);
                #ifndef __SUNPRO_CC
                    return *this;
                #endif
                }

            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const unsigned char* s)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {

                int overflow;
                otl_strcpy
                    ((unsigned char*)this->vl[cur_in]->val(),
                    (unsigned char*)s,
                    overflow,
                    this->vl[cur_in]->elem_size
                    );
                if(overflow)
                {
                    char l_var_info[256];
                    otl_var_info_var
                        (this->vl[cur_in]->name,
                        this->vl[cur_in]->ftype,
                        otl_var_char,
                        l_var_info);
                    throw otl_tmpl_exception
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct>
                        (otl_error_msg_4,
                        otl_error_code_4,
                        this->stm_text,
                        l_var_info);
                #ifndef __SUNPRO_CC
                    return *this;
                #endif
                }

            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const int n)
        {
            check_in_var();
            if(check_in_type(otl_var_int,sizeof(int)))
            {
                *(int*)this->vl[cur_in]->val()=n;
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const unsigned u)
        {
            check_in_var();
            if(check_in_type(otl_var_unsigned_int,sizeof(unsigned)))
            {
                *(unsigned*)this->vl[cur_in]->val()=u;
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const short sh)
        {
            check_in_var();
            if(check_in_type(otl_var_short,sizeof(short)))
            {
                *(short*)this->vl[cur_in]->val()=sh;
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const long int l)
        {
            check_in_var();
            if(check_in_type(otl_var_long_int,sizeof(long)))
            {
                *(long*)this->vl[cur_in]->val()=l;
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const float f)
        {
            check_in_var();
            if(check_in_type(otl_var_float,sizeof(float)))
            {
                *(float*)this->vl[cur_in]->val()=f;
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const double d)
        {
            check_in_var();
            if(check_in_type(otl_var_double,sizeof(double)))
            {
                *(double*)this->vl[cur_in]->val()=d;
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,
            TTimestampStruct>& operator<<(const TTimestampStruct& t)
        {
            check_in_var();
            if(check_in_type(otl_var_timestamp,sizeof(TTimestampStruct)))
            {
                TTimestampStruct* tm=(TTimestampStruct*)this->vl[cur_in]->val();
                memcpy(tm,(void*)&t,sizeof(TTimestampStruct));
            }
            get_in_next();
            return *this;
        }

};

template <class TExceptionStruct,
class TConnectStruct,
class TCursorStruct,
class TVariableStruct,
class TTimestampStruct>
class otl_tmpl_out_stream: public otl_tmpl_cursor
<TExceptionStruct,TConnectStruct,TCursorStruct,
TVariableStruct
>
{
    public:

        int auto_commit_flag;
        int dirty;
        int cur_x;
        int cur_y;
        short array_size;
        int in_exception_flag;
        int in_destruct_flag;
        int should_delete_flag;
        char var_info[256];

        void cleanup(void)
        {
            int i;
            if(should_delete_flag)
            {
                for(i=0;i<this->vl_len;++i)
                    delete this->vl[i];
            }
            delete this->vl;
        }

        otl_tmpl_out_stream
            (short arr_size,
            const char* sqlstm,
            otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db)
            : otl_tmpl_cursor
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>(db)
        {
            int i;
            dirty=0;
            auto_commit_flag=1;
            cur_x=-1;
            cur_y=0;
            should_delete_flag=1;
            in_exception_flag=0;
            in_destruct_flag=0;
            this->stm_text=0;
            array_size=arr_size;
            {
                int len=strlen(sqlstm)+1;
                this->stm_text=new char[len];
                strcpy(this->stm_text,sqlstm);
                otl_tmpl_ext_hv_decl
                    <TVariableStruct,TTimestampStruct,TExceptionStruct,
                    TConnectStruct,TCursorStruct> hvd(this->stm_text,arr_size);
                hvd.alloc_host_var_list(this->vl,this->vl_len,db);
            }
            try
            {
                this->parse();
                for(i=0;i<this->vl_len;++i)
                    bind(*(this->vl[i]));
            }catch(otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>)
            {
                cleanup();
                throw;
            }
        }

        otl_tmpl_out_stream
            (otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db)
            : otl_tmpl_cursor
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>(db)
        {
            should_delete_flag=1;
            in_exception_flag=0;
            in_destruct_flag=0;
            dirty=0;
            auto_commit_flag=1;
            cur_x=-1;
            cur_y=0;
            this->stm_text=0;
        }

        ~otl_tmpl_out_stream()
        {
            in_destruct_flag=1;
            if(dirty&&!in_exception_flag)flush();
            cleanup();
            in_destruct_flag=0;
        }

        virtual void flush(void)
        {
            int i,rc;
            if(!dirty)return;
            if(this->retcode==0||this->adb->retcode==0)
            {
                clean();
                return;                           // buffer is not flushed in case of error
            }
            if(cur_x!=this->vl_len-1)
            {
                in_exception_flag=1;
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_3,
                    otl_error_code_3,
                    this->stm_text,
                    0);
            }
            if(in_destruct_flag)
            {
                this->retcode=this->cursor_struct.exec(cur_y+1);
                for(i=0;i<this->vl_len;++i)
                {
                    rc=this->vl[i]->var_struct.put_blob();
                    if(rc==0)
                    {
                        throw otl_tmpl_exception
                            <TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>(this->adb->connect_struct,this->stm_text);
                    }
                }
                if(!this->retcode)
                {
                    clean();
                    in_exception_flag=1;
                    throw otl_tmpl_exception
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct>(this->cursor_struct,this->stm_text);
                }
                if(auto_commit_flag)
                {
                    this->adb->retcode=this->adb->connect_struct.commit();
                    if(!this->adb->retcode)
                    {
                        clean();
                        throw otl_tmpl_exception
                            <TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>(this->adb->connect_struct,this->stm_text);
                    }
                }
            }
            else
            {
                exec((short)(cur_y+1));
                for(i=0;i<this->vl_len;++i)
                {
                    rc=this->vl[i]->var_struct.put_blob();
                }
                if(auto_commit_flag)
                    this->adb->commit();
                clean();
            }
        }

        virtual void clean(const int clean_up_error_flag=0)
        {
            int i,j;
            if(!dirty)return;
            for(j=0;j<this->vl_len;++j)
                for(i=0;i<this->vl[j]->array_size;++i)
                    if(this->vl[j]->param_type!=OTL_INOUT_PARAM)
                        this->vl[j]->set_not_null(i);
            cur_x=-1;
            cur_y=0;
            dirty=0;
            if(clean_up_error_flag)
                this->retcode=1;
        }

        void set_commit(int auto_commit=0){auto_commit_flag=auto_commit;}

        void get_next(void)
        {
            if(cur_x<this->vl_len-1)
                ++cur_x;
            else
            {
                if(cur_y<array_size-1)
                {
                    ++cur_y;
                    cur_x=0;
                }
                else
                {
                    flush();
                    cur_x=0;
                }
            }
            dirty=1;
        }

        int check_type(int type_code, int tsize)
        {
            if(this->vl[cur_x]->ftype==otl_var_char&&type_code==otl_var_char)
                return 1;
            if(this->vl[cur_x]->ftype!=type_code||this->vl[cur_x]->elem_size!=tsize)
            {
                in_exception_flag=1;
                otl_var_info_var
                    (this->vl[cur_x]->name,
                    this->vl[cur_x]->ftype,
                    type_code,
                    var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    this->stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return 1;
            #endif
            }else
            return 1;
        }

        void check_buf(void)
        {
            if(cur_x==this->vl_len-1 && cur_y==array_size-1)
                flush();
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const char c)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_char,1))
                {
                    char* tmp=(char*)this->vl[cur_x]->val(cur_y);
                    tmp[0]=c;
                    tmp[1]=0;
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const unsigned char c)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_char,1))
                {
                    unsigned char* tmp=(unsigned char*)this->vl[cur_x]->val(cur_y);
                    tmp[0]=c;
                    tmp[1]=0;
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const char* s)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_char,1))
                {

                    int overflow;
                    otl_strcpy
                        ((unsigned char*)this->vl[cur_x]->val(cur_y),
                        (unsigned char*)s,
                        overflow,
                        this->vl[cur_x]->elem_size
                        );
                    if(overflow)
                    {
                        otl_var_info_var
                            (this->vl[cur_x]->name,
                            this->vl[cur_x]->ftype,
                            otl_var_char,
                            var_info);
                        in_exception_flag=1;
                        throw otl_tmpl_exception
                            <TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>
                            (otl_error_msg_4,
                            otl_error_code_4,
                            this->stm_text,
                            var_info);
                    #ifndef __SUNPRO_CC
                        return *this;
                    #endif
                    }
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const unsigned char* s)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_char,1))
                {

                    int overflow;
                    otl_strcpy
                        ((unsigned char*)this->vl[cur_x]->val(cur_y),
                        (unsigned char*)s,
                        overflow,
                        this->vl[cur_x]->elem_size
                        );
                    if(overflow)
                    {
                        otl_var_info_var
                            (this->vl[cur_x]->name,
                            this->vl[cur_x]->ftype,
                            otl_var_char,
                            var_info);
                        in_exception_flag=1;
                        throw otl_tmpl_exception
                            <TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>
                            (otl_error_msg_4,
                            otl_error_code_4,
                            this->stm_text,
                            var_info);
                    #ifndef __SUNPRO_CC
                        return *this;
                    #endif
                    }
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const int n)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_int,sizeof(int)))
                {
                    *(int*)this->vl[cur_x]->val(cur_y)=n;
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

    #ifdef OTL_PL_TAB
        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(otl_pl_tab_generic& tab)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(tab.vtype,tab.elem_size))
                {
                    int i,tmp_len;
                    if(tab.len()<=this->vl[cur_x]->array_size)
                        tmp_len=tab.len();
                    else
                        tmp_len=this->vl[cur_x]->array_size;
                    this->vl[cur_x]->set_pl_tab_len(tmp_len);
                    if(tab.vtype==otl_var_char)
                    {
                        int i;
                        for(i=0;i<tmp_len;++i)
                        {
                            int overflow;
                            otl_strcpy
                                ((unsigned char*)this->vl[cur_x]->val(i),
                                (unsigned char*)tab.val(i),
                                overflow,
                                this->vl[cur_x]->elem_size
                                );
                            if(overflow)
                            {
                                char l_var_info[256];
                                otl_var_info_var
                                    (this->vl[cur_x]->name,
                                    this->vl[cur_x]->ftype,
                                    otl_var_char,
                                    l_var_info);
                                throw otl_tmpl_exception
                                    <TExceptionStruct,
                                    TConnectStruct,
                                    TCursorStruct>
                                    (otl_error_msg_4,
                                    otl_error_code_4,
                                    this->stm_text,
                                    l_var_info);
                            }
                        }
                    }
                    else if(tab.vtype==otl_var_timestamp)
                    {
                        otl_datetime* ext_dt=(otl_datetime*)tab.p_v;
                        otl_oracle_date* int_dt=(otl_oracle_date*)this->vl[cur_x]->val();
                        int j;
                        for(j=0;j<tmp_len;++j)
                        {
                            convert_date(*int_dt,*ext_dt);
                            ++int_dt;
                            ++ext_dt;
                        }
                    }else
                    memcpy((char*)this->vl[cur_x]->val(),(char*)tab.val(),tab.elem_size*tmp_len);
                    for(i=0;i<tmp_len;++i)
                    {
                        if(tab.is_null(i))
                            this->vl[cur_x]->set_null(i);
                        else
                            this->vl[cur_x]->set_not_null(i);
                    }
                }
                check_buf();
            }
            return *this;
        }
    #endif

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const unsigned u)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_unsigned_int,sizeof(unsigned)))
                {
                    *(unsigned *)this->vl[cur_x]->val(cur_y)=u;
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const short sh)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_short,sizeof(short)))
                {
                    *(short*)this->vl[cur_x]->val(cur_y)=sh;
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const long int l)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_long_int,sizeof(long)))
                {
                    *(long*)this->vl[cur_x]->val(cur_y)=l;
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const float f)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_float,sizeof(float)))
                {
                    *(float*)this->vl[cur_x]->val(cur_y)=f;
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const double d)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_double,sizeof(double)))
                {
                    *(double*)this->vl[cur_x]->val(cur_y)=d;
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const otl_null n)
        {
            OTL_UNUSED_ARG(n)
                if(this->vl_len>0)
            {
                get_next();
                this->vl[cur_x]->set_null(cur_y);
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const TTimestampStruct& t)
        {
            if(this->vl_len>0)
            {
                get_next();
                if(check_type(otl_var_timestamp,sizeof(TTimestampStruct)))
                {
                    TTimestampStruct* tm=(TTimestampStruct*)this->vl[cur_x]->val(cur_y);
                    memcpy(tm,(void*)&t,sizeof(TTimestampStruct));
                    this->vl[cur_x]->set_not_null(cur_y);
                }
                check_buf();
            }
            return *this;
        }

        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<(const otl_long_string& s)
        {
            if(this->vl_len>0)
            {
                get_next();

                if(this->vl[cur_x]->ftype==otl_var_varchar_long||
                    this->vl[cur_x]->ftype==otl_var_raw_long)
                {
                    unsigned char* c=(unsigned char*)this->vl[cur_x]->val(cur_y);
                    int len=((otl_long_string*)&s)->len();

                    this->vl[cur_x]->set_not_null(cur_y);

                    if(len>this->vl[cur_x]->actual_elem_size())
                    {
                        otl_var_info_var
                            (this->vl[cur_x]->name,
                            this->vl[cur_x]->ftype,
                            otl_var_char,
                            var_info);
                        throw otl_tmpl_exception
                            <TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>
                            (otl_error_msg_5,
                            otl_error_code_5,
                            this->stm_text,
                            var_info);
                    #ifndef __SUNPRO_CC
                        return *this;
                    #endif
                    }

                    memcpy(c,s.v,len);
                    this->vl[cur_x]->set_len(len);
                }else if(this->vl[cur_x]->ftype==otl_var_blob||
                    this->vl[cur_x]->ftype==otl_var_clob)
                {
                    int len=((otl_long_string*)&s)->len();

                    if(len>this->vl[cur_x]->actual_elem_size())
                    {
                        otl_var_info_var
                            (this->vl[cur_x]->name,
                            this->vl[cur_x]->ftype,
                            otl_var_char,
                            var_info);
                        throw otl_tmpl_exception
                            <TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>
                            (otl_error_msg_5,
                            otl_error_code_5,
                            this->stm_text,
                            var_info);
                    #ifndef __SUNPRO_CC
                        return *this;
                    #endif
                    }
                    this->vl[cur_x]->set_not_null(cur_y);
                    this->vl[cur_x]->var_struct.save_blob(s.v,len,s.extern_buffer_flag);
                }
                check_buf();
            }
            return *this;
        }

    #ifdef OTL_ORA8
        otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator<<
            (otl_tmpl_lob_stream
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>& s)
        {
            if(this->vl_len>0)
            {
                get_next();

                if(this->vl[cur_x]->ftype==otl_var_blob||
                    this->vl[cur_x]->ftype==otl_var_clob)
                {
                    s.init
                        (this->vl[cur_x],
                        this->adb,
                        (otl_tmpl_cursor
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct,
                        TVariableStruct>*)this,
                        0,
                        otl_lob_stream_write_mode);
                }
                check_buf();
            }
            else
            {
//              char l_var_info[256];
                otl_var_info_var
                    (this->vl[cur_x]->name,
                    this->vl[cur_x]->ftype,
                    otl_var_long_string,
                    var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    this->stm_text,
                    var_info);
            }
            return *this;
        }
    #endif

};

template <class TExceptionStruct,
class TConnectStruct,
class TCursorStruct,
class TVariableStruct,
class TTimestampStruct>
class otl_tmpl_inout_stream: public otl_tmpl_out_stream
<TExceptionStruct,TConnectStruct,TCursorStruct,
TVariableStruct,TTimestampStruct
>
{
    public:

        otl_tmpl_variable<TVariableStruct>** in_vl;
        int iv_len;
        int cur_in_x;
        int cur_in_y;
        int in_y_len;
        int null_fetched;
        otl_tmpl_variable<TVariableStruct>** avl;
        int avl_len;
        char var_info[256];

        void cleanup(void)
        {
            int i;
            for(i=0;i<avl_len;++i)
            {
                delete avl[i];
            }
            delete[] avl;
            delete[] in_vl;
        }

        otl_tmpl_inout_stream
            (short arr_size,
            const char* sqlstm,
            otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db)
            : otl_tmpl_out_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TTimestampStruct>(db)
        {
            int i,j;
            this->dirty=0;
            this->auto_commit_flag=1;
            this->adb=&db;
            this->in_exception_flag=0;
            this->stm_text=0;
            this->array_size=arr_size;
            this->should_delete_flag=0;

            in_vl=0;
            iv_len=0;
            avl_len=0;
            avl=0;

            {
                int len=strlen(sqlstm)+1;
                this->stm_text=new char[len];
                strcpy(this->stm_text,sqlstm);
                otl_tmpl_ext_hv_decl
                    <TVariableStruct,TTimestampStruct,TExceptionStruct,
                    TConnectStruct,TCursorStruct> hvd(this->stm_text,arr_size);
                if(hvd.vst[otl_tmpl_ext_hv_decl
                    <TVariableStruct,TTimestampStruct,TExceptionStruct,
                    TConnectStruct,TCursorStruct>::def]==hvd.len)
                {
                    this->should_delete_flag=1;
                    hvd.alloc_host_var_list(this->vl,this->vl_len,db);
                }
                else
                {
                    for(i=0;i<hvd.len;++i)
                    {
                        if(hvd.inout[i]==otl_tmpl_ext_hv_decl
                            <TVariableStruct,
                            TTimestampStruct,
                            TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>::in)
                            ++this->vl_len;
                        else if(hvd.inout[i]==otl_tmpl_ext_hv_decl
                            <TVariableStruct,
                            TTimestampStruct,
                            TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>::out)
                            ++iv_len;
                        else if(hvd.inout[i]==otl_tmpl_ext_hv_decl
                            <TVariableStruct,
                            TTimestampStruct,
                            TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>::io)
                        {
                            ++this->vl_len;
                            ++iv_len;
                        }
                    }
                    if(this->vl_len>0)
                    {
                        this->vl=new otl_tmpl_variable<TVariableStruct>*[this->vl_len];
                    }
                    if(iv_len>0)
                    {
                        in_vl=new otl_tmpl_variable<TVariableStruct>*[iv_len];
                    }
                    if(hvd.len>0)
                    {
                        avl=new otl_tmpl_variable<TVariableStruct>*[hvd.len];
                    }
                    iv_len=0; this->vl_len=0; avl_len=hvd.len;
                    for(j=0;j<avl_len;++j)
                    {
                        if(hvd.pl_tab_size[j]>32767)
                        {
//                          char l_var_info[256];
                            otl_var_info_var
                                (hvd[j],
                                otl_var_none,
                                otl_var_none,
                                var_info);
                            throw otl_tmpl_exception
                                <TExceptionStruct,
                                TConnectStruct,
                                TCursorStruct>
                                (otl_error_msg_6,
                                otl_error_code_6,
                                this->stm_text,
                                var_info);
                        }
                        otl_tmpl_variable<TVariableStruct>* v=hvd.alloc_var
                            (hvd[j],
                            hvd.inout[j],
                            otl_tmpl_ext_hv_decl
                            <TVariableStruct,TTimestampStruct,TExceptionStruct,
                            TConnectStruct,TCursorStruct>::def,
                            db,
                            hvd.pl_tab_size[j]);
                        v->name_pos=j+1;
                        avl[j]=v;
                        if(hvd.inout[j]==otl_tmpl_ext_hv_decl
                            <TVariableStruct,
                            TTimestampStruct,
                            TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>::in)
                        {
                            ++this->vl_len;
                            this->vl[this->vl_len-1]=v;
                            v->set_param_type(OTL_INPUT_PARAM);
                        }else if(hvd.inout[j]==otl_tmpl_ext_hv_decl
                            <TVariableStruct,
                            TTimestampStruct,
                            TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>::out)
                        {
                            ++iv_len;
                            in_vl[iv_len-1]=v;
                            v->set_param_type(OTL_OUTPUT_PARAM);
                        }else if(hvd.inout[j]==otl_tmpl_ext_hv_decl
                            <TVariableStruct,
                            TTimestampStruct,
                            TExceptionStruct,
                            TConnectStruct,
                            TCursorStruct>::io)
                        {
                            ++this->vl_len;
                            ++iv_len;
                            this->vl[this->vl_len-1]=v;
                            in_vl[iv_len-1]=v;
                            v->set_param_type(OTL_INOUT_PARAM);
                        }
                    }
                }
            }

            try
            {
                this->parse();
                for(i=0;i<this->vl_len;++i)
                    bind(*(this->vl[i]));
                for(j=0;j<iv_len;++j)
                    bind(*in_vl[j]);
                rewind();
            }catch(otl_tmpl_exception
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct>)
            {
                cleanup();
                throw;
            }

        }

        ~otl_tmpl_inout_stream()
        {
            if(!this->in_exception_flag)
                flush();
            cleanup();
        }

        int eof(void)
        {
            if(iv_len==0)return 1;
            if(in_y_len==0)return 1;
            if(cur_in_y<=in_y_len-1)return 0;
            return 1;
        }

        void flush(void)
        {
            if(this->vl_len==0)return;
            in_y_len=this->cur_y+1;
            cur_in_y=0;
            cur_in_x=0;
            if(!this->in_exception_flag)
                otl_tmpl_out_stream
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct,
                    TVariableStruct,
                    TTimestampStruct>::flush();
        }

        void clean(const int clean_up_error_flag=0)
        {
            if(this->vl_len==0)return;
            in_y_len=this->cur_y+1;
            cur_in_y=0;
            cur_in_x=0;
            otl_tmpl_out_stream
                <TExceptionStruct,
                TConnectStruct,
                TCursorStruct,
                TVariableStruct,
                TTimestampStruct>::clean
                (clean_up_error_flag);
        }

        void rewind(void)
        {
            flush();
            cur_in_x=0;
            cur_in_y=0;
            this->cur_x=-1;
            this->cur_y=0;
            in_y_len=0;
            null_fetched=0;
            if(this->vl_len==0)
            {
                exec(this->array_size);
                in_y_len=this->array_size;
                cur_in_y=0;
                cur_in_x=0;
            }
        }

        int is_null(void)
        {
            return null_fetched;
        }

        void get_in_next(void)
        {
            if(iv_len==0)return;
            if(in_y_len==0)return;
            if(cur_in_x<iv_len-1)
                ++cur_in_x;
            else
            {
                if(cur_in_y<in_y_len-1)
                {
                    ++cur_in_y;
                    cur_in_x=0;
                }
                else
                {
                    cur_in_y=0;
                    cur_in_x=0;
                    in_y_len=0;
                }
            }
        }

        int check_in_type(int type_code,int tsize)
        {
            if(in_vl[cur_in_x]->ftype==otl_var_char&&type_code==otl_var_char)
                return 1;
            if(in_vl[cur_in_x]->ftype!=type_code||in_vl[cur_in_x]->elem_size!=tsize)
            {
                this->in_exception_flag=1;
                otl_var_info_var
                    (in_vl[cur_in_x]->name,
                    in_vl[cur_in_x]->ftype,
                    type_code,
                    var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    this->stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return 1;
            #endif
            }else
            return 1;
        }

        int is_null_intern(void)
        {
            if(iv_len==0)return 0;
            if(in_y_len==0)return 0;
            if(in_y_len>0)
                return in_vl[cur_in_x]->is_null(cur_in_y);
            return 0;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(char& c)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_char,1))
            {
                c=*(char*)in_vl[cur_in_x]->val(cur_in_y);
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(unsigned char& c)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_char,1))
            {
                c=*(unsigned char*)in_vl[cur_in_x]->val(cur_in_y);
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(char* s)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_char,1))
            {
                strcpy((char*)s,(char*)in_vl[cur_in_x]->val(cur_in_y));
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(unsigned char* s)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_char,1))
            {
                strcpy((char*)s,(char*)in_vl[cur_in_x]->val(cur_in_y));
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(int& n)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_int,sizeof(int)))
            {
                n=*(int*)in_vl[cur_in_x]->val(cur_in_y);
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(unsigned& u)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_unsigned_int,sizeof(unsigned)))
            {
                u=*(unsigned*)in_vl[cur_in_x]->val(cur_in_y);
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(short& sh)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_short,sizeof(short)))
            {
                sh=*(short*)in_vl[cur_in_x]->val(cur_in_y);
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(long int& l)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_long_int,sizeof(long)))
            {
                l=*(long*)in_vl[cur_in_x]->val(cur_in_y);
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(float& f)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_float,sizeof(float)))
            {
                f=*(float*)in_vl[cur_in_x]->val(cur_in_y);
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(double& d)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_double,sizeof(double)))
            {
                d=*(double*)in_vl[cur_in_x]->val(cur_in_y);
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

    #ifdef OTL_PL_TAB
        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(otl_pl_tab_generic& tab)
        {
            if(eof())return *this;
            if(check_in_type(tab.vtype,tab.elem_size))
            {
                int i,tmp_len;
                tmp_len=in_vl[cur_in_x]->get_pl_tab_len();
                if(tab.tab_size<tmp_len)
                    tmp_len=tab.tab_size;
                tab.set_len(tmp_len);
                if(tab.vtype==otl_var_char)
                {
                    for(i=0;i<tmp_len;++i)
                    {
                        int overflow;
                        otl_strcpy
                            ((unsigned char*)tab.val(i),
                            (unsigned char*)in_vl[cur_in_x]->val(i),
                            overflow,
                            tab.elem_size
                            );
                    }
                }
                else if(tab.vtype==otl_var_timestamp)
                {
                    otl_datetime* ext_dt=(otl_datetime*)tab.p_v;
                    otl_oracle_date* int_dt=(otl_oracle_date*)in_vl[cur_in_x]->val();
                    int j;
                    for(j=0;j<tmp_len;++j)
                    {
                        convert_date(*ext_dt,*int_dt);
                        ++int_dt;
                        ++ext_dt;
                    }
                }else
                memcpy((char*)tab.val(),(char*)in_vl[cur_in_x]->val(),tab.elem_size*tmp_len);
                for(i=0;i<tmp_len;++i)
                {
                    if(in_vl[cur_in_x]->is_null(i))
                        tab.set_null(i);
                    else
                        tab.set_non_null(i);
                }
                null_fetched=0;
            }
            get_in_next();
            return *this;
        }
    #endif

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(TTimestampStruct& t)
        {
            if(eof())return *this;
            if(check_in_type(otl_var_timestamp,sizeof(TTimestampStruct)))
            {
                TTimestampStruct* tm=(TTimestampStruct*)in_vl[cur_in_x]->val(cur_in_y);
                memcpy((void*)&t,tm,sizeof(TTimestampStruct));
                null_fetched=is_null_intern();
            }
            get_in_next();
            return *this;
        }

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>(otl_long_string& s)
        {
            if(eof())return *this;
            if(in_vl[cur_in_x]->ftype==otl_var_varchar_long||
                in_vl[cur_in_x]->ftype==otl_var_raw_long)
            {
                unsigned char* c=(unsigned char*)in_vl[cur_in_x]->val(cur_in_y);
                int len=in_vl[cur_in_x]->get_len();
                if(len>s.buf_size)len=s.buf_size;
                memcpy(s.v,c,len);
                s.set_len(len);
                s.v[len]=0;
                s.set_len(len);
                null_fetched=is_null_intern();
            }else if(in_vl[cur_in_x]->ftype==otl_var_clob||
                in_vl[cur_in_x]->ftype==otl_var_blob)
            {
                int len=0;
                int rc=in_vl[cur_in_x]->var_struct.get_blob(cur_in_y,s.v,s.buf_size,len);
                if(rc==0)
                    throw otl_tmpl_exception
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct>(this->adb->connect_struct,this->stm_text);
                if(len>s.buf_size)len=s.buf_size;
                s.set_len(len);
                s.v[len]=0;
                null_fetched=is_null_intern();
            }
            else
            {
                char l_var_info[256];
                otl_var_info_var
                    (in_vl[cur_in_x]->name,
                    in_vl[cur_in_x]->ftype,
                    otl_var_long_string,
                    l_var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    this->stm_text,
                    l_var_info);
            }
            get_in_next();
            return *this;
        }

    #ifdef OTL_ORA8
        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TTimestampStruct>& operator>>
            (otl_tmpl_lob_stream
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>& s)
        {
            if(eof())return *this;
            if(in_vl[cur_in_x]->ftype==otl_var_clob||
                in_vl[cur_in_x]->ftype==otl_var_blob)
            {
                s.init
                    (in_vl[cur_in_x],
                    this->adb,
                    (otl_tmpl_cursor
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct,
                    TVariableStruct>*)this,
                    0,
                    otl_lob_stream_read_mode);
            }
            else
            {
                char l_var_info[256];
                otl_var_info_var
                    (in_vl[cur_in_x]->name,
                    in_vl[cur_in_x]->ftype,
                    otl_var_long_string,
                    l_var_info);
                throw otl_tmpl_exception
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct>
                    (otl_error_msg_0,
                    otl_error_code_0,
                    this->stm_text,
                    l_var_info);
            }
            get_in_next();
            return *this;
        }
    #endif

};

template <class TExceptionStruct,
class TConnectStruct,
class TCursorStruct,
class TVariableStruct,
class TSelectCursorStruct,
class TTimestampStruct>
class otl_tmpl_basic_stream
{
    public:

        otl_tmpl_select_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TSelectCursorStruct,TTimestampStruct>* ss;

        otl_tmpl_inout_stream
            <TExceptionStruct,TConnectStruct,TCursorStruct,
            TVariableStruct,TTimestampStruct>* io;

        otl_select_struct_override override;

        void set_column_type(const int column_ndx,
            const int col_type,
            const int col_size=0)
        {
            override.add_override(column_ndx,col_type,col_size);
        }

        otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>* adb;

        int auto_commit_flag;

        otl_var_desc* iov;
        int iov_len;

        otl_var_desc* ov;
        int ov_len;

        long get_rpc()
        {
            if(io)
                return io->get_rpc();
            else
                return 0;
        }

        void create_var_desc(void)
        {
            int i;
            delete[] iov;
            delete[] ov;
            iov=0; iov_len=0;
            ov=0; ov_len=0;
            if(ss)
            {
                if(ss->vl_len>0)
                {
                    iov=new otl_var_desc[ss->vl_len];
                    iov_len=ss->vl_len;
                    for(i=0;i<ss->vl_len;++i)
                        ss->vl[i]->copy_var_desc(iov[i]);
                }
                if(ss->sl_len>0)
                {
                    ov=new otl_var_desc[ss->sl_len];
                    ov_len=ss->sl_len;
                    for(i=0;i<ss->sl_len;++i)
                        ss->sl[i].copy_var_desc(ov[i]);
                }
            }
            else if(io)
            {
                if(io->vl_len>0)
                {
                    iov=new otl_var_desc[io->vl_len];
                    iov_len=io->vl_len;
                    for(i=0;i<io->vl_len;++i)
                        io->vl[i]->copy_var_desc(iov[i]);
                }
                if(io->iv_len>0)
                {
                    ov=new otl_var_desc[io->iv_len];
                    ov_len=io->iv_len;
                    for(i=0;i<io->iv_len;++i)
                        io->in_vl[i]->copy_var_desc(ov[i]);
                }
            }
        }

        otl_tmpl_basic_stream
            (const short arr_size,
            const char* sqlstm,
            otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db,
            const int implicit_select=otl_explicit_select)
        {
            iov=0; iov_len=0;
            ov=0; ov_len=0;
            io=0; ss=0;
            auto_commit_flag=1;
            adb=&db;
            open(arr_size,sqlstm,db,implicit_select);
        }

        otl_tmpl_basic_stream()
        {
            iov=0; iov_len=0;
            ov=0; ov_len=0;
            io=0; ss=0;
            auto_commit_flag=1;
            adb=0;
        }

        ~otl_tmpl_basic_stream()
        {
            close();
        }

        int eof(void)
        {
            if(io)
                return io->eof();
            else if(ss)
                return ss->eof();
            else
                return 1;
        }

        void flush(void)
        {
            if(io)io->flush();
        }

        void clean(const int clean_up_error_flag=0)
        {
            if(io)io->clean(clean_up_error_flag);
        }

        void rewind(void)
        {
            if(io)
                io->rewind();
            else if(ss)
                ss->rewind();
        }

        int is_null(void)
        {
            if(io)
                return io->is_null();
            else if(ss)
                return ss->is_null();
            else
                return 0;
        }

        otl_column_desc* describe_select(int& desc_len)
        {
            desc_len=0;
            if(!ss)return 0;
            desc_len=ss->sl_len;
            return ss->sl_desc;
        }

        void set_commit(int auto_commit=0)
        {
            auto_commit_flag=auto_commit;
            if(io)io->set_commit(auto_commit);
        }

        void open
            (short arr_size,
            const char* sqlstm,
            otl_tmpl_connect
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct>& db,
            const int implicit_select=otl_explicit_select
            )
        {

            delete[] iov;
            delete[] ov;

            iov=0; iov_len=0;
            ov=0; ov_len=0;

            char tmp[7];
            char* c=(char*)sqlstm;

            while(isspace(*c))++c;
            strncpy(tmp,c,6);
            tmp[6]=0;
            c=tmp;
            while(*c)
            {
                *c=otl_to_upper(*c);
                ++c;
            }
            adb=&db;
            if(strncmp(tmp,"SELECT",6)==0)
            {
                ss=new otl_tmpl_select_stream
                    <TExceptionStruct,
                    TConnectStruct,
                    TCursorStruct,
                    TVariableStruct,
                    TSelectCursorStruct,
                    TTimestampStruct>(&override,arr_size,sqlstm,db);
            }
            else
            {
                if(implicit_select)
                    ss=new otl_tmpl_select_stream
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct,
                        TVariableStruct,
                        TSelectCursorStruct,
                        TTimestampStruct>(&override,arr_size,sqlstm,db,1);
                else
                {
                    io=new otl_tmpl_inout_stream
                        <TExceptionStruct,
                        TConnectStruct,
                        TCursorStruct,
                        TVariableStruct,
                        TTimestampStruct>(arr_size,sqlstm,db);
                }
            }
            if(io)io->set_commit(auto_commit_flag);
            create_var_desc();
        }

        void close(void)
        {
            delete[] iov;
            delete[] ov;

            iov=0; iov_len=0;
            ov=0; ov_len=0;

            delete ss;
            delete io;
            ss=0; io=0;
            adb=0;
        }

        int good(void)
        {
            if(io||ss)
                return 1;
            else
                return 0;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(char& c)
        {
            if(io)
                io->operator>>(c);
            else if(ss)
                ss->operator>>(c);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(unsigned char& c)
        {
            if(io)
                io->operator>>(c);
            else if(ss)
                ss->operator>>(c);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(char* s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(unsigned char* s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(int& n)
        {
            if(io)
                io->operator>>(n);
            else if(ss)
                ss->operator>>(n);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(unsigned& u)
        {
            if(io)
                io->operator>>(u);
            else if(ss)
                ss->operator>>(u);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(short& sh)
        {
            if(io)
                io->operator>>(sh);
            else if(ss)
                ss->operator>>(sh);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(long int& l)
        {
            if(io)
                io->operator>>(l);
            else if(ss)
                ss->operator>>(l);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(float& f)
        {
            if(io)
                io->operator>>(f);
            else if(ss)
                ss->operator>>(f);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(double& d)
        {
            if(io)
                io->operator>>(d);
            else if(ss)
                ss->operator>>(d);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(TTimestampStruct& t)
        {
            if(io)
                io->operator>>(t);
            else if(ss)
                ss->operator>>(t);
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>(otl_long_string& s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            return *this;
        }

    #ifdef OTL_ORA8
        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator>>
            (otl_tmpl_lob_stream
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>& s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            return *this;
        }
    #endif

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const char c)
        {
            if(io)
                io->operator<<(c);
            else if(ss)
            {
                ss->operator<<(c);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const unsigned char c)
        {
            if(io)
                io->operator<<(c);
            else if(ss)
            {
                ss->operator<<(c);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const char* s)
        {
            if(io)
                io->operator<<(s);
            else if(ss)
            {
                ss->operator<<(s);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const unsigned char* s)
        {
            if(io)
                io->operator<<(s);
            else if(ss)
            {
                ss->operator<<(s);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const int n)
        {
            if(io)
                io->operator<<(n);
            else if(ss)
            {
                ss->operator<<(n);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const unsigned u)
        {
            if(io)
                io->operator<<(u);
            else if(ss)
            {
                ss->operator<<(u);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const short sh)
        {
            if(io)
                io->operator<<(sh);
            else if(ss)
            {
                ss->operator<<(sh);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const long int l)
        {
            if(io)
                io->operator<<(l);
            else if(ss)
            {
                ss->operator<<(l);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const float f)
        {
            if(io)
                io->operator<<(f);
            else if(ss)
            {
                ss->operator<<(f);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const double d)
        {
            if(io)
                io->operator<<(d);
            else if(ss)
            {
                ss->operator<<(d);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const TTimestampStruct& t)
        {
            if(io)
                io->operator<<(t);
            else if(ss)
            {
                ss->operator<<(t);
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const otl_long_string& s)
        {
            if(io)io->operator<<(s);
            return *this;
        }

    #ifdef OTL_ORA8
        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<
            (otl_tmpl_lob_stream
            <TExceptionStruct,
            TConnectStruct,
            TCursorStruct,
            TVariableStruct>& s)
        {
            if(io)io->operator<<(s);
            return *this;
        }
    #endif

        otl_tmpl_basic_stream
            <TExceptionStruct,TConnectStruct,
            TCursorStruct,TVariableStruct,
            TSelectCursorStruct,TTimestampStruct>& operator<<(const otl_null n)
        {
            OTL_UNUSED_ARG(n)
                if(io)io->operator<<(otl_null());
            if(ss)
            {
                ss->operator<<(otl_null());
                if(!ov&&ss->sl) create_var_desc();
            }
            return *this;
        }

};

// ==================== OTL-Adapter for ODBC =========================
#ifdef OTL_ODBC
#ifndef _WINDOWS_
#include <windows.h>
#endif
#include <sql.h>
#include <sqlext.h>
OTL_ODBC_NAMESPACE_BEGIN

typedef TIMESTAMP_STRUCT otl_time;

class otl_exc
{
    public:
        unsigned char msg[1000];
        int code;
        unsigned char sqlstate[1000];

        enum{disabled=0,enabled=1};

        otl_exc()
        {
            sqlstate[0]=0;
            code=0;
            msg[0]=0;
        }

        void init(const char* amsg, const int acode)
        {
            strcpy((char*)msg,amsg);
            code=acode;
            sqlstate[0]=0;
        }

};

class otl_conn
{
    public:

        HENV henv;
        HDBC hdbc;

        int timeout;
        int cursor_type;
        int status;
        int long_max_size;

        static int initialize(const int threaded_mode=0)
        {
            OTL_UNUSED_ARG(threaded_mode)
                return 1;
        }

        otl_conn()
        {
            timeout=0;
            cursor_type=0;
            henv=0;
            hdbc=0;
            long_max_size=32760;
            status=SQL_SUCCESS;
        }

        ~otl_conn()
        {
            status=SQLFreeHandle(SQL_HANDLE_DBC,hdbc);
            hdbc=0;
            status=SQLFreeHandle(SQL_HANDLE_ENV,henv);
            henv=0;
        }

        void set_timeout(const int atimeout=0)
        {
            timeout=atimeout;
        }

        void set_cursor_type(const int acursor_type=0)
        {
            cursor_type=acursor_type;
        }

        int rlogon(const char* connect_str,const int auto_commit)
        {
            char username[256];
            char passwd[256];
            char tnsname[256];
            char* tnsname_ptr=0;
            char* c=(char*) connect_str;
            char* username_ptr=username;
            char* passwd_ptr=passwd;
            char temp_connect_str[512];

            memset(username,0,sizeof(username));
            memset(passwd,0,sizeof(passwd));
            memset(tnsname,0,sizeof(tnsname));

            char* c1=(char*)connect_str;
            int oracle_format=0;

            while(*c1)
            {
                if(*c1=='@')
                {
                    oracle_format=1;
                    break;
                }
                ++c1;
            }

            if(oracle_format)
            {
                while(*c&&*c!='/')
                {
                    *username_ptr=*c;
                    ++c;
                    ++username_ptr;
                }
                *username_ptr=0;

                if(*c=='/')++c;
                while(*c&&*c!='@')
                {
                    *passwd_ptr=*c;
                    ++c;
                    ++passwd_ptr;
                }
                *passwd_ptr=0;

                if(*c=='@')
                {
                    ++c;
                    tnsname_ptr=tnsname;
                    while(*c)
                    {
                        *tnsname_ptr=*c;
                        ++c;
                        ++tnsname_ptr;
                    }
                    *tnsname_ptr=0;
                }
            }
            else
            {
                c1=(char*)connect_str;
                char* c2=temp_connect_str;
                while(*c1)
                {
                    *c2=otl_to_upper(*c1);
                    ++c1;
                    ++c2;
                }
                *c2=0;
                c1=temp_connect_str;
                char entry_name[256];
                char entry_value[256];
                while(*c1)
                {
                    c2=entry_name;
                    while(*c1&&*c1!='=')
                    {
                        *c2=*c1;
                        ++c1;
                        ++c2;
                    }
                    *c2=0;
                    if(*c1) ++c1;
                    c2=entry_value;
                    while(*c1&&*c1!=';')
                    {
                        *c2=*c1;
                        ++c1;
                        ++c2;
                    }
                    *c2=0;
                    if(*c1) ++c1;
                    if(strcmp(entry_name,"DSN")==0)strcpy(tnsname,entry_value);
                    if(strcmp(entry_name,"UID")==0)strcpy(username,entry_value);
                    if(strcmp(entry_name,"PWD")==0)strcpy(passwd,entry_value);
                }
            }

            if(henv==0||hdbc==0)
            {
                status=SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv);
                if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
                status=SQLSetEnvAttr(henv,SQL_ATTR_ODBC_VERSION,(void*)SQL_OV_ODBC3,SQL_NTS);
                if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
                status=SQLAllocHandle(SQL_HANDLE_DBC,henv,&hdbc);
                if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            }

            if(oracle_format)
            {
                status=SQLConnect
                    (hdbc,
                    (unsigned char*)tnsname,SQL_NTS,
                    (unsigned char*)username,SQL_NTS,
                    (unsigned char*)passwd,SQL_NTS);
            }
            else
            {
                SQLCHAR out_str[2048];
                SQLSMALLINT out_len=0;
                status=SQLDriverConnect
                    (hdbc,
                    0,
                    (SQLCHAR*)connect_str,
                    (short)strlen(connect_str),
                    out_str,
                    sizeof(out_str),
                    &out_len,
                    SQL_DRIVER_NOPROMPT);
            }

            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                return 0;
            if(auto_commit)
                status=SQLSetConnectAttr
                    (hdbc,
                    SQL_ATTR_AUTOCOMMIT,
                    (SQLPOINTER)SQL_AUTOCOMMIT_ON,
                    SQL_NTS);
            else
                status=SQLSetConnectAttr
                    (hdbc,
                    SQL_ATTR_AUTOCOMMIT,
                    (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
                    SQL_NTS);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            return 1;

        }

        int logoff(void)
        {
	    orgin: commit();
            status=SQLDisconnect(hdbc);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                return 0;
            else
                return 1;
        }

        void error(otl_exc& exception_struct)
        {
            RETCODE rc;
            SWORD msg_len;
            rc=SQLGetDiagRec
                (SQL_HANDLE_DBC,
                hdbc,
                1,
                (UCHAR FAR*)&exception_struct.sqlstate[0],
                (SDWORD FAR*)&exception_struct.code,
                (UCHAR FAR*)&exception_struct.msg[0],
                SQL_MAX_MESSAGE_LENGTH-1,
                (SWORD FAR*)&msg_len);
            exception_struct.msg[msg_len]=0;
        }

        int commit(void)
        {
            status=SQLEndTran(SQL_HANDLE_DBC,hdbc,SQL_COMMIT);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                return 0;
            else
                return 1;
        }

        int rollback(void)
        {
            status=SQLEndTran(SQL_HANDLE_DBC,hdbc,SQL_ROLLBACK);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                return 0;
            else
                return 1;
        }

};

class otl_var
{
    public:

        unsigned char* p_v;
        SDWORD* p_len;
        int ftype;
        int act_elem_size;

        otl_var()
        {
            p_v=0;
            p_len=0;
            act_elem_size=0;
        }

        ~otl_var()
        {
            delete p_v;
            delete p_len;
        }

        int put_blob(void)
        {
            return 1;
        }

        int get_blob
            (const int ndx,
            unsigned char* abuf,
            const int buf_size,
            int& len)
        {
            OTL_UNUSED_ARG(ndx)
                OTL_UNUSED_ARG(abuf)
                OTL_UNUSED_ARG(buf_size)
                OTL_UNUSED_ARG(len)
                return 1;
        }

        int save_blob
            (const unsigned char* abuf,
            const int len,
            const int extern_buffer_flag)
        {
            OTL_UNUSED_ARG(abuf)
                OTL_UNUSED_ARG(len)
                OTL_UNUSED_ARG(extern_buffer_flag)
                return 1;
        }

        int actual_elem_size(void)
        {
            return act_elem_size;
        }

        void init
            (const int aftype,
            const int aelem_size,
            const short aarray_size,
            const void* connect_struct=0,
            const int apl_tab_size=0)
        {
            int i;
            OTL_UNUSED_ARG(connect_struct)
                OTL_UNUSED_ARG(apl_tab_size)
                ftype=aftype;
            act_elem_size=aelem_size;
            p_v=new unsigned char[aelem_size*(unsigned)aarray_size];
            p_len=new SDWORD[aarray_size];
            memset(p_v,0,aelem_size*(unsigned)aarray_size);
            for(i=0;i<aarray_size;++i)
            {
                if(ftype==otl_var_char)
                    p_len[i]=(SDWORD)SQL_NTS;
                else if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
                    p_len[i]=0;
                else
                    p_len[i]=(SDWORD)aelem_size;
            }
        }

        void set_null(int ndx)
        {
            p_len[ndx]=SQL_NULL_DATA;
        }

        void set_not_null(int ndx, int pelem_size)
        {
            set_len(pelem_size,ndx);
        }

        void set_len(int len, int ndx)
        {
            if(ftype==otl_var_char)
                p_len[ndx]=SQL_NTS;
            else
                p_len[ndx]=(SDWORD)len;
        }

        int get_len(int ndx)
        {
            if(p_len[ndx]==SQL_NULL_DATA)
                return 0;
            else
                return p_len[ndx];
        }

        int is_null(int ndx)
        {
            return p_len[ndx]==SQL_NULL_DATA;
        }

        void* val(int ndx,int pelem_size)
        {
            return (void*)&p_v[((unsigned)ndx)*pelem_size];
        }

        static int int2ext(int int_type)
        {
            switch(int_type)
            {
                case SQL_VARCHAR: return SQL_C_CHAR;
                case SQL_DATE: return SQL_C_DATE;
                case SQL_TYPE_TIMESTAMP: return SQL_C_TIMESTAMP;
                case SQL_CHAR: return SQL_C_CHAR;
                case SQL_BIGINT: return SQL_C_DOUBLE;
                case SQL_DECIMAL: return SQL_C_DOUBLE;
                case SQL_DOUBLE: return SQL_C_DOUBLE;
                case SQL_FLOAT: return SQL_C_DOUBLE;
                case SQL_INTEGER: return SQL_C_SLONG;
                case SQL_NUMERIC: return SQL_C_DOUBLE;
                case SQL_REAL: return SQL_C_DOUBLE;
                case SQL_SMALLINT: return SQL_C_SSHORT;
                case SQL_TYPE_TIME: return SQL_C_TIME;
                case SQL_TINYINT: return SQL_C_SSHORT;
                case SQL_LONGVARCHAR: return SQL_LONGVARCHAR;
                case SQL_LONGVARBINARY: return SQL_LONGVARBINARY;
                case -9: return SQL_C_CHAR;
                default: return -1;
            }
        }

        static int datatype_size(int ftype,int maxsz,int int_type,int max_long_size)
        {
            switch(ftype)
            {
                case SQL_C_CHAR:
                    switch(int_type)
                    {
                        case SQL_LONGVARCHAR:
                            return max_long_size;
                        case SQL_LONGVARBINARY:
                            return max_long_size;
                        case SQL_DATE:
                            return 40;
                        case SQL_TYPE_TIMESTAMP:
                            return 40;
                        case SQL_TYPE_TIME:
                            return 40;
                        default:
                            return maxsz+1;
                    }
                case SQL_C_DOUBLE:
                    return sizeof(double);
                case SQL_C_SLONG:
                    return sizeof(int);
                case SQL_C_SSHORT:
                    return sizeof(short int);
                case SQL_C_TIMESTAMP:
                    return sizeof(TIMESTAMP_STRUCT);
                case SQL_C_TIME:
                    return sizeof(TIME_STRUCT);
                case SQL_C_DATE:
                    return sizeof(DATE_STRUCT);
                case SQL_LONGVARCHAR:
                    return max_long_size;
                case SQL_LONGVARBINARY:
                    return max_long_size;
                default:
                    return 0;
            }
        }

        static void map_ftype
            (otl_column_desc& desc,
            const int max_long_size,
            int& ftype,
            int& elem_size,
            otl_select_struct_override& override,
            const int column_ndx)
        {
            int ndx=override.find(column_ndx);
            if(ndx==-1)
            {
                ftype=int2ext(desc.dbtype);
                elem_size=datatype_size(ftype,desc.dbsize,desc.dbtype,max_long_size);
                switch(ftype)
                {
                    case SQL_C_CHAR:
                        ftype=otl_var_char;
                        break;
                    case SQL_C_DOUBLE:
                        ftype=otl_var_double;
                        break;
                    case SQL_C_SLONG:
                        ftype=otl_var_int;
                        break;
                    case SQL_C_SSHORT:
                        ftype=otl_var_short;
                        break;
                    case SQL_LONGVARCHAR:
                        ftype=otl_var_varchar_long;
                        break;
                    case SQL_LONGVARBINARY:
                        ftype=otl_var_raw_long;
                        break;
                    case SQL_C_DATE:
                    case SQL_C_TIME:
                    case SQL_C_TIMESTAMP:
                        ftype=otl_var_timestamp;
                        break;
                    default:
                        ftype=0;
                        break;
                }
            }
            else
            {
                ftype=override.col_type[ndx];
                switch(ftype)
                {
                    case otl_var_char:
                        elem_size=override.col_size[ndx];
                        break;
                    case otl_var_double:
                        elem_size=sizeof(double);
                        break;
                    case otl_var_float:
                        elem_size=sizeof(float);
                        break;
                    case otl_var_int:
                        elem_size=sizeof(int);
                        break;
                    case otl_var_unsigned_int:
                        elem_size=sizeof(unsigned);
                        break;
                    case otl_var_short:
                        elem_size=sizeof(short);
                        break;
                    case otl_var_long_int:
                        elem_size=sizeof(double);
                        break;
                    default:
                        elem_size=override.col_size[ndx];
                        break;
                }
            }
            desc.otl_var_dbtype=ftype;
        }

};

class otl_cur
{
    public:

        HSTMT cda;
        int status;
        otl_conn* adb;
        int direct_exec_flag;
        long _rpc;

        otl_cur()
        {
            cda=0;
            adb=0;
            _rpc=0;
            direct_exec_flag=0;
        }

        ~otl_cur(){}

        void set_direct_exec(const int flag)
        {
            direct_exec_flag=flag;
        }

        int open(otl_conn& connect)
        {
            direct_exec_flag=0;
            adb=&connect;
            status=SQLAllocHandle(SQL_HANDLE_STMT,connect.hdbc,&cda);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            if(connect.timeout>0)
            {
                status=SQLSetStmtAttr
                    (cda,SQL_ATTR_QUERY_TIMEOUT,(void*)connect.timeout,SQL_NTS);
                if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            }
            if(connect.cursor_type!=0)            // other than default
            {
                status=SQLSetStmtAttr
                    (cda,SQL_ATTR_CURSOR_TYPE,(void*)connect.cursor_type,SQL_NTS);
                if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            }
            return 1;
        }

        int close(void)
        {
            status=SQLFreeStmt(cda,SQL_DROP);
            adb=0;
            cda=0;
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                return 0;
            else
                return 1;
        }

        int parse(char* stm_text)
        {
            short in_str=0;
            char *c=stm_text;

            if(direct_exec_flag)
            {
                _rpc=0;
                status=SQLExecDirect
                    (cda,
                    (UCHAR FAR*)stm_text,
                    SQL_NTS);
                if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                    return 0;
                else
                {
                    SQLINTEGER tmp_rpc=0;
                    SQLRETURN diag_status=SQLGetDiagField
                        (SQL_HANDLE_STMT,
                        cda,
                        (SQLSMALLINT)0,
                        (SQLSMALLINT)SQL_DIAG_ROW_COUNT,
                        (SQLPOINTER)&tmp_rpc,
                        SQL_IS_INTEGER,
                        (SQLSMALLINT*)-1);
                    if(diag_status==SQL_SUCCESS||diag_status==SQL_SUCCESS_WITH_INFO)
                        _rpc=(long)tmp_rpc;
                    return 1;
                }
            }

            // Converting : notation into ODBC's native notation ?
            while(*c)
            {
                if(*c=='\'')
                {
                    if(!in_str)
                        in_str=1;
                    else
                    {
                        if(c[1]=='\'')
                            ++c;
                        else
                            in_str=0;
                    }
                }
                if(*c==':'&&!in_str)
                {
                    *c='?';
                    ++c;
                    while(isdigit(*c)||isalpha(*c)||*c=='_')
                    {
                        *c=' ';
                        ++c;
                    }
                }
                ++c;
            }

            status=SQLPrepare
                (cda,
                (unsigned char*)stm_text,
                SQL_NTS);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                return 0;
            else
                return 1;
        }

        int exec(const int iters)
        {
            if(direct_exec_flag)
            {
                return 1;
            }
            else
            {
                status=SQLSetStmtAttr
                    (cda,SQL_ATTR_PARAMSET_SIZE,(void*)iters,SQL_NTS);
                if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
                _rpc=0;
                status=SQLExecute(cda);
                if(status!=SQL_SUCCESS&&
                    status!=SQL_SUCCESS_WITH_INFO&&
                    status!=SQL_NO_DATA)return 0;
                SQLINTEGER tmp_rpc=0;
                SQLRETURN diag_status=SQLGetDiagField
                    (SQL_HANDLE_STMT,
                    cda,
                    (SQLSMALLINT)0,
                    (SQLSMALLINT)SQL_DIAG_ROW_COUNT,
                    (SQLPOINTER)&tmp_rpc,
                    SQL_IS_INTEGER,
                    (SQLSMALLINT*)-1);
                if(diag_status==SQL_SUCCESS||diag_status==SQL_SUCCESS_WITH_INFO)
                    _rpc=(long)tmp_rpc;
                return 1;
            }
        }

        long get_rpc()
        {
            return _rpc;
        }

        int tmpl_ftype2odbc_ftype(const int ftype)
        {
            switch(ftype)
            {
                case otl_var_char:
                    return SQL_C_CHAR;
                case otl_var_double:
                    return SQL_C_DOUBLE;
                case otl_var_float:
                    return SQL_C_FLOAT;
                case otl_var_int:
                    return SQL_C_SLONG;
                case otl_var_unsigned_int:
                    return SQL_C_ULONG;
                case otl_var_short:
                    return SQL_C_SSHORT;
                case otl_var_timestamp:
                    return SQL_C_TIMESTAMP;
                case otl_var_varchar_long:
                    return SQL_LONGVARCHAR;
                case otl_var_raw_long:
                    return SQL_LONGVARBINARY;
                default:
                    return 0;
            }
        }

        int otl_map_ext2int(int ftype)
        {
            switch(ftype)
            {
                case SQL_LONGVARCHAR: return SQL_LONGVARCHAR;
                case SQL_LONGVARBINARY: return SQL_LONGVARBINARY;
                case SQL_C_CHAR: return SQL_VARCHAR;
                case SQL_C_DATE: return SQL_DATE;
                case SQL_C_TIME: return SQL_TYPE_TIME;
                case SQL_C_TIMESTAMP: return SQL_TYPE_TIMESTAMP;
                case SQL_C_DOUBLE: return SQL_DOUBLE;
                case SQL_C_FLOAT: return SQL_DOUBLE;
                case SQL_C_SLONG: return SQL_DOUBLE;
                case SQL_C_SSHORT: return SQL_DOUBLE;
                case SQL_C_ULONG: return SQL_DOUBLE;
                default: return -1;
            }
        }

        int bind
            (const char* name,
            otl_var& v,
            const int aelem_size,
            const int aftype,
            const int aparam_type,
            const int name_pos,
            const int apl_tab_size)
        {
            SWORD ftype=(SWORD)tmpl_ftype2odbc_ftype(aftype);
            SWORD ftype_save=ftype;
            int param_type;
            int parm_pos=name_pos;
            OTL_UNUSED_ARG(name)
                OTL_UNUSED_ARG(apl_tab_size)
            //  int parm_pos=atoi(&name[1]);
                switch(aparam_type)
            {
                case OTL_INPUT_PARAM:
                    param_type=SQL_PARAM_INPUT;
                    break;
                case OTL_OUTPUT_PARAM:
                    param_type=SQL_PARAM_OUTPUT;
                    break;
                case OTL_INOUT_PARAM:
                    param_type=SQL_PARAM_INPUT_OUTPUT;
                    break;
                default:
                    param_type=SQL_PARAM_INPUT;
                    break;
            }
            if(ftype==SQL_LONGVARCHAR)
                ftype=SQL_C_CHAR;
            else if(ftype==SQL_LONGVARBINARY)
                ftype=SQL_C_BINARY;
            int sqltype=otl_map_ext2int(ftype_save);
            status=SQLBindParameter
                (cda,
                (UWORD)parm_pos,
                (short)param_type,
                ftype,
                (short)sqltype,
                sqltype==SQL_TYPE_TIMESTAMP?23:aelem_size,
                0,
                (PTR)v.p_v,
                (SDWORD)aelem_size,
                v.p_len);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                return 0;
            else
                return 1;
        }

        int bind
            (const int column_num,
            otl_var& v,
            const int elem_size,
            const int aftype,
            const int param_type)
        {
            SWORD ftype=(SWORD)tmpl_ftype2odbc_ftype(aftype);
            OTL_UNUSED_ARG(param_type)
                if(ftype==SQL_LONGVARCHAR)
                ftype=SQL_C_CHAR;
            else if(ftype==SQL_LONGVARBINARY)
                ftype=SQL_C_BINARY;
            status=SQLBindCol
                (cda,
                (unsigned short)column_num,
                ftype,
                (PTR)v.p_v,
                (SDWORD)elem_size,
                &v.p_len[0]);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)
                return 0;
            else
                return 1;
        }

        int describe_column
            (otl_column_desc& col,
            const int column_num,
            int& eof_desc)
        {
            UCHAR  name[256];
            SWORD  nlen;
            SWORD  dbtype;
            SDWORD dbsize;
            SWORD  scale;
            UDWORD prec;
            SWORD  nullok;
            SWORD icols;

            eof_desc=0;
            status=SQLNumResultCols(cda,&icols);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            if(column_num>icols)
            {
                eof_desc=1;
                return 0;
            }
            status=SQLDescribeCol
                (cda,
                (unsigned short)column_num,
                name,
                sizeof(name),
                &nlen,
                &dbtype,
                &prec,
                &scale,
                &nullok);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            dbsize=prec;
            strcpy(col.name,(char*)name);
            col.dbtype=dbtype;
            col.dbsize=dbsize;
            col.scale=scale;
            col.prec=prec;
            col.nullok=nullok;
            return 1;
        }

        void error(otl_exc& exception_struct)
        {
            RETCODE rc;
            SWORD msg_len;
            rc=SQLGetDiagRec
                (SQL_HANDLE_STMT,
                cda,
                1,
                (UCHAR FAR*)&exception_struct.sqlstate[0],
                (SDWORD FAR*)&exception_struct.code,
                (UCHAR FAR*)&exception_struct.msg[0],
                SQL_MAX_MESSAGE_LENGTH-1,
                (SWORD FAR*)&msg_len);
            exception_struct.msg[msg_len]=0;
        }

};

class otl_sel
{
    public:

        int implicit_cursor;
        UWORD* row_status;
        int status;
        UDWORD crow;

        otl_sel()
        {
            implicit_cursor=0;
        }

        ~otl_sel(){}

        void set_select_type(const int atype)
        {
            implicit_cursor=atype;
        }

        void init(const int array_size){OTL_UNUSED_ARG(array_size)}

        int first
            (otl_cur& cur,
            int& cur_row,
            int& cur_size,
            int& row_count,
            int& eof_data,
            const int array_size)
        {
            cur_row=-1;
            eof_data=0;
            status=SQLSetStmtAttr
                (cur.cda,SQL_ATTR_ROW_ARRAY_SIZE,(void*)array_size,SQL_NTS);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            status=SQLSetStmtAttr
                (cur.cda,SQL_ATTR_ROWS_FETCHED_PTR,&crow,SQL_NTS);
            if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            if(!implicit_cursor)
            {
                status=SQLExecute(cur.cda);
                if(status!=SQL_SUCCESS&&status!=SQL_SUCCESS_WITH_INFO)return 0;
            }
            status=SQLFetchScroll(cur.cda,SQL_FETCH_NEXT,1);
            if(status==SQL_ERROR||
                status==SQL_INVALID_HANDLE)
                return 0;
            if(status==SQL_NO_DATA_FOUND)
            {
                eof_data=1;
                cur_row=-1;
                status=SQLFreeStmt(cur.cda,SQL_CLOSE);
                if(status==SQL_ERROR)return 0;
                return 1;
            }
            row_count=crow;
            cur_size=row_count;
            if(cur_size!=0)cur_row=0;
            return 1;
        }

        int next
            (otl_cur& cur,
            int& cur_row,
            int& cur_size,
            int& row_count,
            int& eof_data,
            const int array_size)
        {
            OTL_UNUSED_ARG(array_size)
                if(cur_row<cur_size-1)
            {
                ++cur_row;
                return 1;
            }
            else
            {
                if(eof_data)
                {
                    cur_row=-1;
                    cur_size=0;
                    return 1;
                }
                status=SQLFetchScroll(cur.cda,SQL_FETCH_NEXT,1);
                if(status==SQL_ERROR||
                    status==SQL_SUCCESS_WITH_INFO||
                    status==SQL_INVALID_HANDLE)
                    return 0;
                if(status==SQL_NO_DATA_FOUND)
                {
                    eof_data=1;
                    cur_row=-1;
                    cur_size=0;
                    status=SQLFreeStmt(cur.cda,SQL_CLOSE);
                    if(status==SQL_ERROR)return 0;
                    return 1;
                }
                cur_size=crow;
                row_count+=crow;
                if(cur_size!=0)cur_row=0;
                return 1;
            }
        }

};

typedef otl_tmpl_connect
<otl_exc,
otl_conn,
otl_cur> otl_connect;

typedef otl_tmpl_cursor
<otl_exc,
otl_conn,
otl_cur,
otl_var> otl_cursor;

typedef otl_tmpl_exception
<otl_exc,
otl_conn,
otl_cur> otl_exception;

typedef otl_tmpl_basic_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var,
otl_sel,
otl_time> otl_basic_stream;

class otl_stream: public otl_tmpl_basic_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var,
otl_sel,
otl_time>
{
    public:

        otl_stream()
            :otl_tmpl_basic_stream
            <otl_exc,
            otl_conn,
            otl_cur,
            otl_var,
            otl_sel,
            otl_time>(){}

        otl_stream
            (const short arr_size,
            const char* sqlstm,
            otl_connect& db,
            const int implicit_select=otl_explicit_select)
            : otl_tmpl_basic_stream
            <otl_exc,
            otl_conn,
            otl_cur,
            otl_var,
            otl_sel,
            otl_time>(arr_size,sqlstm,db,implicit_select)
            {}

        void open
            (short int arr_size,
            const char* sqlstm,
            otl_connect& db,
            const int implicit_select=otl_explicit_select)
        {
            otl_tmpl_basic_stream
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var,
                otl_sel,
                otl_time>::open(arr_size,sqlstm,db,implicit_select);
        }

        otl_stream& operator<<(const otl_datetime& s)
        {
            otl_time tmp;
            tmp.year=s.year;
            tmp.month=s.month;
            tmp.day=s.day;
            tmp.hour=s.hour;
            tmp.minute=s.minute;
            tmp.second=s.second;
            tmp.fraction=0;
            (*(otl_tmpl_basic_stream
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var,
                otl_sel,
                otl_time>*)this)<<tmp;
            return *this;
        }

        otl_stream& operator>>(otl_datetime& s)
        {
            otl_time tmp;
            (*(otl_tmpl_basic_stream
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var,
                otl_sel,
                otl_time>*)this)>>tmp;
            s.year=tmp.year;
            s.month=tmp.month;
            s.day=tmp.day;
            s.hour=tmp.hour;
            s.minute=tmp.minute;
            s.second=tmp.second;
            return *this;
        }

        otl_stream& operator>>(int& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(char& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(unsigned char& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(char* n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(unsigned char* n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(unsigned& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(short& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(long int& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(float& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(double& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(otl_time& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator>>(otl_long_string& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)>>n;
            return *this;
        }

        otl_stream& operator<<(const char n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const unsigned char n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const char* n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const unsigned char* n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const int n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const unsigned n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const short n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const long int n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const float n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const double n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const otl_time& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const otl_long_string& n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

        otl_stream& operator<<(const otl_null n)
        {
            (*(otl_tmpl_basic_stream
                <otl_exc,otl_conn,otl_cur,otl_var,otl_sel,otl_time>*)
                this)<<n;
            return *this;
        }

};

class otl_nocommit_stream: public otl_stream
{
    public:

        otl_nocommit_stream(): otl_stream()
        {
            set_commit(0);
        }

        otl_nocommit_stream
            (const short arr_size,
            const char* sqlstm,
            otl_connect& db,
            const int implicit_select=otl_explicit_select)
            : otl_stream(arr_size,sqlstm,db,implicit_select)
        {
            set_commit(0);
        }

        void open
            (short int arr_size,
            const char* sqlstm,
            otl_connect& db,
            const int implicit_select=otl_explicit_select)
        {
            otl_stream::open(arr_size,sqlstm,db,implicit_select);
            set_commit(0);
        }

};

OTL_ODBC_NAMESPACE_END
#endif

// ==================== OTL-Adapter for Oracle 7 =====================
#ifdef OTL_ORA7
extern "C"
{
    #include <ociapr.h>
}


OTL_ORA7_NAMESPACE_BEGIN

const int inVarChar2=1;
const int inNumber=2;
const int inLong=8;
const int inRowId=11;
const int inDate=12;
const int inRaw=23;
const int inLongRaw=24;
const int inChar=96;
const int inMslabel=106;

const int  extVarChar2=inVarChar2;
const int  extNumber=inNumber;
const int  extInt=3;
const int  extFloat=4;
const int  extCChar=5;
const int  extVarNum=6;
const int  extLong=inLong;
const int  extVarChar=9;
const int  extRowId=inRowId;
const int  extDate=inDate;
const int  extVarRaw=15;
const int  extRaw=inRaw;
const int  extLongRaw=inLongRaw;
const int  extUInt=68;
const int  extLongVarChar=94;
const int  extLongVarRaw=95;
const int  extChar=inChar;
const int  extCharZ=97;
const int  extMslabel=inMslabel;

typedef otl_oracle_date otl_time0;

class otl_exc
{
    public:
        unsigned char msg[1000];
        int code;

        char sqlstate[32];

        enum{disabled=0,enabled=1};

        otl_exc()
        {
            sqlstate[0]=0;
        }

        void init(const char* amsg, const int acode)
        {
            strcpy((char*)msg,amsg);
            code=acode;
        }

};

class otl_conn
{
    public:

        Lda_Def* lda;
        unsigned char hda[512];
        int extern_lda;

        static int initialize(const int threaded_mode=0)
        {
            if(threaded_mode)
                return !opinit(1);
            else
                return 1;
        }

        otl_conn()
        {
            lda=0;
            extern_lda=0;
        }

        ~otl_conn()
        {
            delete lda;
        }

        void set_timeout(const int atimeout=0){OTL_UNUSED_ARG(atimeout)}
        void set_cursor_type(const int acursor_type=0){OTL_UNUSED_ARG(acursor_type)}

        int ext_logon(Lda_Def* ext_lda,const int auto_commit)
        {
            int rc;
            lda=ext_lda;
            extern_lda=1;
            if(auto_commit)
            {
                rc=ocon(lda);
                if(rc)
                    return 0;
                else
                    return 1;
            }
            return 1;
        }

        int rlogon(const char* connect_str,const int auto_commit)
        {
            if(!extern_lda)delete lda;
            lda=new Lda_Def;
            extern_lda=0;
            memset(lda,0,sizeof(*lda));
            memset(hda,0,sizeof(hda));
            int rc=olog(lda,
                hda,
                (unsigned char*)connect_str,
                -1,
                0,
                -1,
                0,
                -1,
                0
                );
            if(rc)return 0;
            if(!auto_commit)return 1;
            rc=ocon(lda);
            if(rc)
                return 0;
            else
                return 1;
        }

        int logoff(void)
        {
            if(extern_lda)
            {
                lda=0;
                extern_lda=0;
                return 1;
            }
            else
            {
                int rc=ologof(lda);
                delete lda;
                lda=0;
                return !rc;
            }
        }

        void error(otl_exc& exception_struct)
        {
            int len;
            exception_struct.code=lda->rc;
            oerhms
                (lda,
                lda->rc,
                exception_struct.msg,
                sizeof(exception_struct.msg)
                );
            len = strlen((const char*)exception_struct.msg);
            exception_struct.msg[len]=0;
        }

        int commit(void)
        {
            return !ocom(lda);
        }

        int rollback(void)
        {
            return !orol(lda);
        }

};

class otl_var
{
    public:

        ub1* p_v;
        sb2* p_ind;
        ub2* p_rlen;
        ub2* p_rcode;
        int ftype;
        int act_elem_size;
        int array_size;
        ub4 max_tab_len;
        ub4 cur_tab_len;
        int pl_tab_flag;

        otl_var()
        {
            p_v=0;
            p_ind=0;
            p_rlen=0;
            p_rcode=0;
            act_elem_size=0;
            max_tab_len=0;
            cur_tab_len=0;
            pl_tab_flag=0;
        }

        ~otl_var()
        {
            delete p_v;
            delete p_ind;
            delete p_rlen;
            delete p_rcode;
        }

        int actual_elem_size(void)
        {
            return act_elem_size;
        }

        void init
            (const int aftype,
            const int aelem_size,
            const short aarray_size,
            const void* connect_struct=0,
            const int apl_tab_flag=0)
        {
            int i,elem_size;
            OTL_UNUSED_ARG(connect_struct)
                ftype=aftype;
            pl_tab_flag=apl_tab_flag;
            act_elem_size=aelem_size;
            if(aftype==otl_var_varchar_long||aftype==otl_var_raw_long)
            {
                elem_size=aelem_size+sizeof(sb4);
                array_size=1;
            }
            else
            {
                elem_size=aelem_size;
                array_size=aarray_size;
            }

            p_v=new ub1[elem_size*(unsigned)array_size];
            p_ind=new sb2[array_size];
            p_rlen=new ub2[array_size];
            p_rcode=new ub2[array_size];
            memset(p_v,0,elem_size*(unsigned)array_size);

            if(aftype==otl_var_varchar_long||aftype==otl_var_raw_long)
            {
                if(aelem_size>32760)
                    p_ind[0]=0;
                else
                    p_ind[0]=(short)aelem_size;
                p_rcode[0]=0;
            }
            else
            {
                for(i=0;i<array_size;++i)
                {
                    p_ind[i]=(short)elem_size;
                    p_rlen[i]=(short)elem_size;
                    p_rcode[i]=0;
                }
            }
            max_tab_len=(ub4)array_size;
            cur_tab_len=(ub4)array_size;
        }

        void set_pl_tab_len(const int apl_tab_len)
        {
            max_tab_len=(ub4)array_size;
            cur_tab_len=(ub4)apl_tab_len;
        }

        int get_pl_tab_len(void)
        {
            return (int)cur_tab_len;
        }

        int get_max_pl_tab_len(void)
        {
            return (int)max_tab_len;
        }

        int put_blob(void)
        {
            return 1;
        }

        int get_blob
            (const int ndx,
            unsigned char* abuf,
            const int buf_size,
            int& len)
        {
            OTL_UNUSED_ARG(ndx)
                OTL_UNUSED_ARG(abuf)
                OTL_UNUSED_ARG(buf_size)
                OTL_UNUSED_ARG(len)
                return 1;
        }

        int save_blob
            (const unsigned char* abuf,
            const int len,
            const int extern_buffer_flag)
        {
            OTL_UNUSED_ARG(abuf)
                OTL_UNUSED_ARG(len)
                OTL_UNUSED_ARG(extern_buffer_flag)
                return 1;
        }

        void set_null(int ndx)
        {
            p_ind[ndx]=-1;
        }

        void set_not_null(int ndx, int pelem_size)
        {
            if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
                p_ind[0]=0;
            else
                p_ind[ndx]=(short)pelem_size;
        }

        void set_len(int len, int ndx)
        {
            if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
                *(sb4*)p_v=len;
            else
                p_rlen[ndx]=(short)len;
        }

        int get_len(int ndx)
        {
            if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
                return *(sb4*)p_v;
            else
                return p_rlen[ndx];
        }

        int is_null(int ndx)
        {
            return p_ind[ndx]==-1;
        }

        void* val(int ndx,int pelem_size)
        {
            if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
                return (void*)(p_v+sizeof(sb4));
            else
                return (void*)&p_v[((unsigned)ndx)*pelem_size];
        }

        static int int2ext(int int_type)
        {
            switch(int_type)
            {
                case inVarChar2: return extCChar;
                case inNumber:   return extFloat;
                case inLong:     return extLongVarChar;
                case inRowId:    return extCChar;
                case inDate:     return extDate;
                case inRaw:      return extCChar;
                case inLongRaw:  return extLongVarRaw;
                case inChar:     return extCChar;
                default:
                    return -1;
            }
        }

        static int datatype_size(int ftype,int maxsz,int int_type,int max_long_size)
        {
            switch(ftype)
            {
                case extCChar:
                    switch(int_type)
                    {
                        case inRowId:
                            return 30;
                        case inDate:
                            return otl_oracle_date_size;
                        case inRaw:
                            return maxsz*2+1;
                        default:
                            return maxsz+1;
                    }
                case extLongVarChar:
                    return max_long_size;
                case extLongVarRaw:
                    return max_long_size;
                case extFloat:
                    return sizeof(double);
                case extDate:
                    return otl_oracle_date_size;
                default:
                    return 0;
            }
        }

        static void map_ftype
            (otl_column_desc& desc,
            const int max_long_size,
            int& ftype,
            int& elem_size,
            otl_select_struct_override& override,
            const int column_ndx)
        {
            int ndx=override.find(column_ndx);
            if(ndx==-1)
            {
                ftype=int2ext(desc.dbtype);
                elem_size=datatype_size(ftype,desc.dbsize,desc.dbtype,max_long_size);
                switch(ftype)
                {
                    case extCChar:
                        ftype=otl_var_char;
                        break;
                    case extFloat:
                        ftype=otl_var_double;
                        break;
                    case extLongVarChar:
                        ftype=otl_var_varchar_long;
                        break;
                    case extLongVarRaw:
                        ftype=otl_var_raw_long;
                        break;
                    case extDate:
                        ftype=otl_var_timestamp;
                        break;
                }
            }
            else
            {
                ftype=override.col_type[ndx];
                switch(ftype)
                {
                    case otl_var_char:
                        elem_size=override.col_size[ndx];
                        break;
                    case otl_var_double:
                        elem_size=sizeof(double);
                        break;
                    case otl_var_float:
                        elem_size=sizeof(float);
                        break;
                    case otl_var_int:
                        elem_size=sizeof(int);
                        break;
                    case otl_var_unsigned_int:
                        elem_size=sizeof(unsigned);
                        break;
                    case otl_var_short:
                        elem_size=sizeof(short);
                        break;
                    case otl_var_long_int:
                        elem_size=sizeof(double);
                        break;
                    default:
                        elem_size=override.col_size[ndx];
                        break;
                }
            }
            desc.otl_var_dbtype=ftype;
        }

};

class otl_cur
{
    public:

        Cda_Def cda;

        ub4& rpc;                                 // reference to "rows processed count"
        ub2& ft;                                  // reference to "OCI function code"
        ub2& rc;                                  // reference to "V7 return code"
        ub2& peo;                                 // reference to "parse error offset"

        otl_cur& operator=(const otl_cur& cur)
        {
            rpc=cur.rpc;
            ft=cur.ft;
            rc=cur.rc;
            peo=cur.peo;
            memcpy((void*)&cda,(void*)&cur.cda,sizeof(cda));
            return *this;
        }

        otl_cur()
            : rpc(cda.rpc), ft(cda.ft), rc(cda.rc), peo(cda.peo)
        {
            memset(&cda,0,sizeof(cda));
        }

        ~otl_cur(){}

        long get_rpc()
        {
            return rpc;
        }

        void set_direct_exec(const int flag){OTL_UNUSED_ARG(flag)}

        int open(otl_conn& connect)
        {
            memset(&cda,0,sizeof(cda));
            return !oopen(&cda,connect.lda,0,-1,-1,0,-1);
        }

        int close(void)
        {
            return !oclose(&cda);
        }

        int parse(const char* stm_text)
        {
            return !oparse(&cda,(unsigned char*)stm_text,-1,0,0);
        }

        int exec(const int iters)
        {
            return !oexn(&cda,iters,0);
        }

        int fetch(const short iters,int& eof_data)
        {
            int rc=ofen(&cda,iters);
            eof_data=0;
            if(cda.rc==1403)
            {
                eof_data=1;
                return 1;
            }else if(rc==0)
            return 1;
            else
                return 0;
        }

        int tmpl_ftype2ora_ftype(const int ftype)
        {
            switch(ftype)
            {
                case otl_var_char:
                    return extCChar;
                case otl_var_double:
                    return extFloat;
                case otl_var_float:
                    return extFloat;
                case otl_var_int:
                    return extInt;
                case otl_var_long_int:
                    return extInt;
                case otl_var_unsigned_int:
                    return extUInt;
                case otl_var_short:
                    return extInt;
                case otl_var_timestamp:
                    return extDate;
                case otl_var_varchar_long:
                    return extLongVarChar;
                case otl_var_raw_long:
                    return extLongVarRaw;
                default:
                    return 0;
            }
        }

        int bind
            (const char* name,
            otl_var& v,
            const int elem_size,
            const int ftype,
            const int param_type,
            const int name_pos,
            const int apl_tab_flag)
        {
            OTL_UNUSED_ARG(name_pos)
                OTL_UNUSED_ARG(param_type)
                if(apl_tab_flag)
                return !obndra(&cda,
                    (unsigned char*)name,
                    -1,
                    (ub1*)v.p_v,
                    elem_size,
                    tmpl_ftype2ora_ftype(ftype),
                    -1,
                    v.p_ind,
                    v.p_rlen,
                    v.p_rcode,
                    v.max_tab_len,
                    &v.cur_tab_len,
                    0,
                    -1,
                    -1);
            else
                return !obndrv
                    (&cda,
                    (unsigned char*)name,
                    -1,
                    (ub1*)v.p_v,
                    elem_size,
                    tmpl_ftype2ora_ftype(ftype),
                    -1,
                    v.p_ind,
                    0,
                    -1,
                    -1);
        }

        int bind
            (const int column_num,
            otl_var& v,
            const int elem_size,
            const int ftype,
            const int param_type)
        {
            OTL_UNUSED_ARG(param_type)

                return !odefin
                (&cda,
                column_num,
                (ub1*)v.p_v,
                elem_size,
                tmpl_ftype2ora_ftype(ftype),
                -1,
                v.p_ind,
                0,
                -1,
                -1,
                v.p_rlen,
                v.p_rcode);
        }

        int describe_column
            (otl_column_desc& col,
            const int column_num,
            int& eof_desc)
        {
            sb1  name[241];
            sb4  nlen;
            sb4  dbsize;
            sb2  dbtype;

            sb2  scale;
            sb2  prec;
            sb4  dsize;
            sb2  nullok;

            nlen=sizeof(name);
            int rc=odescr
                (&cda,
                column_num,
                &dbsize,
                &dbtype,
                &name[0],
                &nlen,
                &dsize,
                &prec,
                &scale,
                &nullok);
            if(rc==0)name[nlen]=0;
            eof_desc=0;
            if(cda.rc==1007)
            {
                eof_desc=1;
                return 0;
            }
            if(rc==0)
            {
                strcpy(col.name,(char*)name);
                col.dbtype=dbtype;
                col.dbsize=dbsize;
                col.scale=scale;
                col.prec=prec;
                col.nullok=nullok;
                return 1;
            }else
            return 0;
        }

        void error(otl_exc& exception_struct)
        {
            int len;
            exception_struct.code=cda.rc;
            oerhms
                (&cda,
                cda.rc,
                exception_struct.msg,
                sizeof(exception_struct.msg)
                );
            len = strlen((const char*)exception_struct.msg);
            exception_struct.msg[len]=0;
        }

};

class otl_sel
{
    public:

        int implicit_cursor;

        otl_sel()
        {
            implicit_cursor=0;
        }

        ~otl_sel(){}

        void set_select_type(const int atype)
        {
            OTL_UNUSED_ARG(atype)
                implicit_cursor=0;
        }

        void init(const int array_size){OTL_UNUSED_ARG(array_size)}

        int first
            (otl_cur& cur,
            int& cur_row,
            int& cur_size,
            int& row_count,
            int& eof_data,
            const int array_size)
        {
            int rc;
            eof_data=0;
            cur_row=-1;
            rc=cur.exec(1);
            if(rc==0)return 0;
            rc=cur.fetch((short)array_size,eof_data);
            if(rc==0)return 0;
            row_count=cur.rpc;
            cur_size=row_count;
            if(cur_size!=0)cur_row=0;
            return 1;
        }

        int next
            (otl_cur& cur,
            int& cur_row,
            int& cur_size,
            int& row_count,
            int& eof_data,
            const int array_size)
        {
            int rc;
            if(cur_row<cur_size-1)
            {
                ++cur_row;
                return 1;
            }
            else
            {
                if(eof_data)
                {
                    cur_row=-1;
                    cur_size=0;
                    return 1;
                }
                rc=cur.fetch((short)array_size,eof_data);
                if(rc==0)return 0;
                cur_size=cur.rpc-row_count;
                row_count=cur.rpc;
                if(cur_size!=0)cur_row=0;
                return 1;
            }
        }

};

typedef otl_tmpl_connect
<otl_exc,
otl_conn,
otl_cur> otl_ora7_connect;

typedef otl_tmpl_cursor
<otl_exc,
otl_conn,
otl_cur,
otl_var> otl_cursor;

typedef otl_tmpl_exception
<otl_exc,
otl_conn,
otl_cur> otl_exception;

typedef otl_tmpl_inout_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var,
otl_time0> otl_inout_stream;

typedef otl_tmpl_select_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var,
otl_sel,
otl_time0> otl_select_stream;

typedef otl_tmpl_basic_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var,
otl_sel,
otl_time0> otl_basic_stream;

typedef otl_tmpl_ext_hv_decl
<otl_var,
otl_time0,
otl_exc,
otl_conn,
otl_cur> otl_ext_hv_decl;

class otl_connect: public otl_ora7_connect
{
    public:

        otl_connect():otl_ora7_connect(){}
        otl_connect(const char* connect_str, const int aauto_commit=0)
            : otl_ora7_connect(connect_str, aauto_commit){}

        ~otl_connect(){}

        void rlogon(Lda_Def* alda)
        {
            connected=0;
            long_max_size=32760;
            retcode=connect_struct.ext_logon(alda,0);
            if(retcode)
                connected=1;
            else
            {
                connected=0;
                throw otl_exception(connect_struct);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
        }

        void rlogon(const char* connect_str, const int aauto_commit=0)
        {
            otl_ora7_connect::rlogon(connect_str,aauto_commit);
        }

};

// ============ OTL Reference Cursor Streams for Oracle 7 =================

typedef otl_tmpl_variable<otl_var> otl_generic_variable;
typedef otl_generic_variable* otl_p_generic_variable;

class otl_ref_cursor: public
otl_tmpl_cursor
<otl_exc,
otl_conn,
otl_cur,
otl_var>
{
    public:

        int cur_row;
        int cur_size;
        int row_count;
        int array_size;

        otl_ref_cursor
            (otl_connect& db,
            const char* cur_placeholder_name,
            const short arr_size=1)
            :otl_tmpl_cursor
            <otl_exc,
            otl_conn,
            otl_cur,
            otl_var>(db)
        {
            int i;
            cur_row=-1;
            row_count=0;
            cur_size=0;
            array_size=arr_size;
            rvl_len=otl_var_list_size;
            vl_cur_len=0;
            rvl=new otl_p_generic_variable[rvl_len];
            for(i=0;i<rvl_len;++i)rvl[i]=0;
            strcpy(cur_placeholder,cur_placeholder_name);
        }

        otl_ref_cursor():
        otl_tmpl_cursor
            <otl_exc,
            otl_conn,
            otl_cur,
            otl_var>(),
            sel_cur()
        {
        }

        ~otl_ref_cursor()
        {
            delete[] rvl;
            rvl=0;
        }

        void open
            (otl_connect& db,
            const char* cur_placeholder_name,
            const short arr_size=1)
        {
            int i;
            cur_row=-1;
            row_count=0;
            cur_size=0;
            array_size=arr_size;
            rvl_len=otl_var_list_size;
            vl_cur_len=0;
            rvl=new otl_p_generic_variable[rvl_len];
            for(i=0;i<rvl_len;++i)rvl[i]=0;
            strcpy(cur_placeholder,cur_placeholder_name);
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::open(db);
        }

        void close(void)
        {
            delete[] rvl;
            rvl=0;
            sel_cur.close();
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::close();
        }

        int first(void)
        {
            int i,rc;
            rc=obndrv
                (&cursor_struct.cda,
                (unsigned char*)cur_placeholder,
                -1,
                (ub1*)&sel_cur.cursor_struct.cda,
                sizeof(sel_cur.cursor_struct.cda),
                102,-1,0,0,-1,-1);
            if(rc!=0)throw otl_exception(cursor_struct,stm_text);
            if(cur_row==-2)
                ;                                 // Special case -- calling describe_select() between parse() and first()
            else
            {
                exec(1);                          // Executing the PLSQL master block
                sel_cur.connected=1;
            }
            cur_row=-1;
            for(i=0;i<vl_cur_len;++i)
                sel_cur.bind(i+1,*rvl[i]);
            rc=sel_cur.cursor_struct.fetch((short)array_size,sel_cur.eof_data);
            if(rc==0)throw otl_exception(sel_cur.cursor_struct,stm_text);
            row_count=sel_cur.cursor_struct.cda.rpc;
            cur_size=row_count;
            if(cur_size!=0)cur_row=0;
            return cur_size!=0;
        }

        int next(void)
        {
            int rc;
            if(cur_row<0)return first();
            if(cur_row<cur_size-1)
                ++cur_row;
            else
            {
                if(sel_cur.eof())
                {
                    cur_row=-1;
                    return 0;
                }
                rc=sel_cur.cursor_struct.fetch((short)array_size,sel_cur.eof_data);
                if(rc==0)throw otl_exception(sel_cur.cursor_struct,stm_text);
                cur_size=sel_cur.cursor_struct.cda.rpc-row_count;
                row_count=sel_cur.cursor_struct.cda.rpc;
                if(cur_size!=0)cur_row=0;
            }
            return cur_size!=0;
        }

        void bind
            (const int column_num,
            otl_generic_variable& v)
        {
            if(!connected)return;
            ++vl_cur_len;
            rvl[vl_cur_len-1]=&v;
            v.pos=column_num;
        }

        void bind(otl_generic_variable& v)
        {
            if(v.pos)
                bind(v.pos,v);
            else if(v.name)
                otl_tmpl_cursor
                        <otl_exc,
                        otl_conn,
                        otl_cur,
                        otl_var>::bind(v);
        }

        void bind
            (const char* name,
            otl_generic_variable& v)
        {
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::bind(name,v);
        }

        int describe_select
            (otl_column_desc* desc,
            int& desc_len)
        {
            int i,rc;
            rc=obndrv
                (&cursor_struct.cda,
                (unsigned char*)cur_placeholder,
                -1,
                (ub1*)&sel_cur.cursor_struct.cda,
                sizeof(sel_cur.cursor_struct.cda),
                102,-1,0,0,-1,-1);
            if(rc!=0)throw otl_exception(cursor_struct,stm_text);
            exec(1);                              // Executing the PLSQL master block
            sel_cur.connected=1;
            cur_row=-2;                           // Special case -- describe_select() before first() or next()
            desc_len=0;
            for(i=1;sel_cur.describe_column(desc[i-1],i);++i)
                ++desc_len;
            return 1;
        }

    protected:

        int rvl_len;
        otl_p_generic_variable* rvl;
        int vl_cur_len;
        otl_cursor sel_cur;
        char cur_placeholder[64];

};

class otl_ref_select_stream: public otl_ref_cursor
{
    public:

        otl_select_struct_override* override;

        void cleanup(void)
        {
            int i;
            delete[] sl;
            for(i=0;i<vl_len;++i)
                delete vl[i];
            delete[] vl;
            delete[] sl_desc;
        }

        otl_ref_select_stream
            (otl_select_struct_override* aoverride,
            const short arr_size,
            const char* sqlstm,
            const char* cur_placeholder,
            otl_connect& db)
            :otl_ref_cursor(db,cur_placeholder,arr_size)
        {
            init();

            {
                int len=strlen(sqlstm)+1;
                stm_text=new char[len];
                strcpy(stm_text,sqlstm);
                otl_ext_hv_decl hvd(stm_text,1);
                hvd.alloc_host_var_list(vl,vl_len,*adb);
            }
            override=aoverride;
            try
            {
                parse();
                if(vl_len==0)
                {
                    rewind();
                    null_fetched=0;
                }
            }
            catch(otl_exception)
            {
                cleanup();
                throw;
            }

        }

        ~otl_ref_select_stream()
        {
            cleanup();
        }

        void rewind(void)
        {
            get_select_list();
            ret_code=first();
            null_fetched=0;
            cur_col=-1;
            cur_in=0;
            executed=1;
        }

        int is_null(void)
        {
            return null_fetched;
        }

        int eof(void)
        {
            return !ret_code;
        }

        otl_ref_select_stream& operator>>(otl_time0& t)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_timestamp)&&!eof())
            {
                otl_time0* tm=(otl_time0*)sl[cur_col].val(cur_row);
                memcpy((void*)&t,tm,otl_oracle_date_size);
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(char& c)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                c=*(char*)sl[cur_col].val(cur_row);
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(unsigned char& c)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                c=*(unsigned char*)sl[cur_col].val(cur_row);
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(char* s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                strcpy((char*)s,(char*)sl[cur_col].val(cur_row));
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(unsigned char* s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                strcpy((char*)s,(char*)sl[cur_col].val(cur_row));
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(int& n)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_int
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    n);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_int))
                        n=(int)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(unsigned& u)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_unsigned
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    u);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_unsigned_int))
                        u=(unsigned)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(short& sh)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_short
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    sh);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_short))
                        sh=(short)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(long int& l)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_long_int
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    l);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_long_int))
                        l=(long int)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(float& f)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_float
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    f);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_float))
                        f=(float)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(double& d)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_double
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    d);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_double))
                        d=*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(otl_long_string& s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if((sl[cur_col].ftype==otl_var_varchar_long||
                sl[cur_col].ftype==otl_var_raw_long)&&
                !eof())
            {
                unsigned char* c=(unsigned char*)sl[cur_col].val(cur_row);
                int len=sl[cur_col].get_len(cur_row);
                if(len>s.buf_size)len=s.buf_size;
                memcpy(s.v,c,len);
                s.v[len]=0;
                s.set_len(len);
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator<<(const otl_time0& t)
        {
            check_in_var();
            if(check_in_type(otl_var_timestamp,otl_oracle_date_size))
            {
                otl_time0* tm=(otl_time0*)vl[cur_in]->val();
                memcpy(tm,(void*)&t,otl_oracle_date_size);
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const otl_null n)
        {
            OTL_UNUSED_ARG(n)
                check_in_var();
            vl[cur_in]->set_null(0);
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const char c)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {
                char* tmp=(char*)vl[cur_in]->val();
                tmp[0]=c;
                tmp[1]=0;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const unsigned char c)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {
                unsigned char* tmp=(unsigned char*)vl[cur_in]->val();
                tmp[0]=c;
                tmp[1]=0;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const char* s)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {

                int overflow;
                otl_strcpy
                    ((unsigned char*)vl[cur_in]->val(),
                    (unsigned char*)s,
                    overflow,
                    vl[cur_in]->elem_size
                    );
                if(overflow)
                {
                    char var_info[256];
                    otl_var_info_var
                        (vl[cur_in]->name,
                        vl[cur_in]->ftype,
                        otl_var_char,
                        var_info);
                    throw otl_exception
                        (otl_error_msg_4,
                        otl_error_code_4,
                        stm_text,
                        var_info);
                #ifndef __SUNPRO_CC
                    return *this;
                #endif
                }

            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const unsigned char* s)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {

                int overflow;
                otl_strcpy
                    ((unsigned char*)vl[cur_in]->val(),
                    (unsigned char*)s,
                    overflow,
                    vl[cur_in]->elem_size
                    );
                if(overflow)
                {
                    char var_info[256];
                    otl_var_info_var
                        (vl[cur_in]->name,
                        vl[cur_in]->ftype,
                        otl_var_char,
                        var_info);
                    throw otl_exception
                        (otl_error_msg_4,
                        otl_error_code_4,
                        stm_text,
                        var_info);
                #ifndef __SUNPRO_CC
                    return *this;
                #endif
                }

            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const int n)
        {
            check_in_var();
            if(check_in_type(otl_var_int,sizeof(int)))
            {
                *(int*)vl[cur_in]->val()=n;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const unsigned u)
        {
            check_in_var();
            if(check_in_type(otl_var_unsigned_int,sizeof(unsigned)))
            {
                *(unsigned*)vl[cur_in]->val()=u;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const short sh)
        {
            check_in_var();
            if(check_in_type(otl_var_short,sizeof(short)))
            {
                *(short*)vl[cur_in]->val()=sh;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const long int l)
        {
            check_in_var();
            if(check_in_type(otl_var_long_int,sizeof(long)))
            {
                *(long*)vl[cur_in]->val()=l;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const float f)
        {
            check_in_var();
            if(check_in_type(otl_var_float,sizeof(float)))
            {
                *(float*)vl[cur_in]->val()=f;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const double d)
        {
            check_in_var();
            if(check_in_type(otl_var_double,sizeof(double)))
            {
                *(double*)vl[cur_in]->val()=d;
            }
            get_in_next();
            return *this;
        }

        int select_list_len(void)
        {
            return sl_len;
        }

        int column_ftype(int ndx=0)
        {
            return sl[ndx].ftype;
        }

        int column_size(int ndx=0)
        {
            return sl[ndx].elem_size;
        }

        otl_column_desc* sl_desc;
        int sl_len;
        otl_generic_variable* sl;

    protected:

        int null_fetched;
        int ret_code;
        int cur_col;
        int cur_in;
        int executed;
        char var_info[256];

        void init(void)
        {
            sl=0;
            sl_len=0;
            null_fetched=0;
            ret_code=0;
            sl_desc=0;
            executed=0;
            cur_in=0;
            stm_text=0;
        }

        void get_next(void)
        {
            if(cur_col<sl_len-1)
            {
                ++cur_col;
                null_fetched=sl[cur_col].is_null(cur_row);
            }
            else
            {
                ret_code=next();
                cur_col=0;
            }
        }

        int check_type(int type_code, int actual_data_type=0)
        {
            int out_type_code;
            if(actual_data_type!=0)
                out_type_code=actual_data_type;
            else
                out_type_code=type_code;
            if(sl[cur_col].ftype!=type_code)
            {
                otl_var_info_col
                    (sl[cur_col].pos,
                    sl[cur_col].ftype,
                    out_type_code,
                    var_info);
                throw otl_exception
                    (otl_error_msg_0,
                    otl_error_code_0,
                    stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return 0;
            #endif
            }else
            return 1;
        }

        void look_ahead(void)
        {
            if(cur_col==sl_len-1)
            {
                ret_code=next();
                cur_col=-1;
            }
        }

        void get_select_list(void)
        {
            int i,j,rc;

            otl_auto_array_ptr<otl_column_desc> loc_ptr(otl_var_list_size);
            otl_column_desc* sl_desc_tmp=loc_ptr.ptr;
            int sld_tmp_len=0;
            int ftype,elem_size;

            rc=obndrv
                (&cursor_struct.cda,
                (unsigned char*)cur_placeholder,
                -1,
                (ub1*)&sel_cur.cursor_struct.cda,
                sizeof(sel_cur.cursor_struct.cda),
                102,-1,0,0,-1,-1);
            if(rc!=0)throw otl_exception(cursor_struct,stm_text);

            for(i=0;i<vl_len;++i)otl_tmpl_cursor
                    <otl_exc,
                    otl_conn,
                    otl_cur,
                    otl_var>::bind(*vl[i]);
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::exec(1);                // Executing the PLSQL master block
            sel_cur.connected=1;
            cur_row=-2;
            sld_tmp_len=0;
            for(i=1;sel_cur.describe_column(sl_desc_tmp[i-1],i);++i)
                ++sld_tmp_len;
            sl_len=sld_tmp_len;
            if(sl)
            {
                delete[] sl;
                sl=0;
            }
            sl=new otl_generic_variable[sl_len];
            int max_long_size=adb->get_max_long_size();
            for(j=0;j<sl_len;++j)
            {
                otl_generic_variable::map_ftype
                    (sl_desc_tmp[j],max_long_size,ftype,elem_size,*override,j+1);
                sl[j].copy_pos(j+1);
                sl[j].init(ftype,
                    elem_size,
                    (short)array_size,
                    &adb->connect_struct
                    );
            }
            if(sl_desc)
            {
                delete[] sl_desc;
                sl_desc=0;
            }
            sl_desc=new otl_column_desc[sl_len];
            memcpy(sl_desc,sl_desc_tmp,sizeof(otl_column_desc)*sl_len);
            for(i=0;i<sl_len;++i)sel_cur.bind(sl[i]);
        }

        void get_in_next(void)
        {
            if(cur_in==vl_len-1)
                rewind();
            else
            {
                ++cur_in;
                executed=0;
            }
        }

        int check_in_type(int type_code,int tsize)
        {
            if(vl[cur_in]->ftype==otl_var_char&&type_code==otl_var_char)
                return 1;
            if(vl[cur_in]->ftype!=type_code||vl[cur_in]->elem_size!=tsize)
            {
                otl_var_info_var
                    (vl[cur_in]->name,
                    vl[cur_in]->ftype,
                    type_code,
                    var_info);
                throw otl_exception
                    (otl_error_msg_0,
                    otl_error_code_0,
                    stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return 1;
            #endif
            }else
            return 1;
        }

        void check_in_var(void)
        {
            if(vl_len==0)
                throw otl_exception
                    (otl_error_msg_1,
                    otl_error_code_1,
                    stm_text,
                    0);
        }

        void check_if_executed(void)
        {
            if(!executed)
                throw otl_exception
                    (otl_error_msg_2,
                    otl_error_code_2,
                    stm_text,
                    0);
        }

};

class otl_stream
{
    public:

        otl_select_struct_override override;

        otl_ref_select_stream* ref_ss;
        otl_select_stream* ss;
        otl_inout_stream* io;
        otl_connect* adb;

        int auto_commit_flag;

        otl_var_desc* iov;
        int iov_len;

        otl_var_desc* ov;
        int ov_len;

        long get_rpc()
        {
            if(io)
                return io->get_rpc();
            else
                return 0;
        }

        void create_var_desc(void)
        {
            int i;
            delete[] iov;
            delete[] ov;
            iov=0; iov_len=0;
            ov=0; ov_len=0;
            if(ss)
            {
                if(ss->vl_len>0)
                {
                    iov=new otl_var_desc[ss->vl_len];
                    iov_len=ss->vl_len;
                    for(i=0;i<ss->vl_len;++i)
                        ss->vl[i]->copy_var_desc(iov[i]);
                }
                if(ss->sl_len>0)
                {
                    ov=new otl_var_desc[ss->sl_len];
                    ov_len=ss->sl_len;
                    for(i=0;i<ss->sl_len;++i)
                        ss->sl[i].copy_var_desc(ov[i]);
                }
            }
            else if(io)
            {
                if(io->vl_len>0)
                {
                    iov=new otl_var_desc[io->vl_len];
                    iov_len=io->vl_len;
                    for(i=0;i<io->vl_len;++i)
                        io->vl[i]->copy_var_desc(iov[i]);
                }
                if(io->iv_len>0)
                {
                    ov=new otl_var_desc[io->iv_len];
                    ov_len=io->iv_len;
                    for(i=0;i<io->iv_len;++i)
                        io->in_vl[i]->copy_var_desc(ov[i]);
                }
            }
            else if(ref_ss)
            {
                if(ref_ss->vl_len>0)
                {
                    iov=new otl_var_desc[ref_ss->vl_len];
                    iov_len=ref_ss->vl_len;
                    for(i=0;i<ref_ss->vl_len;++i)
                        ref_ss->vl[i]->copy_var_desc(iov[i]);
                }
                if(ref_ss->sl_len>0)
                {
                    ov=new otl_var_desc[ref_ss->sl_len];
                    ov_len=ref_ss->sl_len;
                    for(i=0;i<ref_ss->sl_len;++i)
                        ref_ss->sl[i].copy_var_desc(ov[i]);
                }
            }
        }

        void set_column_type(const int column_ndx,
            const int col_type,
            const int col_size=0)
        {
            override.add_override(column_ndx,col_type,col_size);
        }

        otl_stream
            (const short arr_size,
            const char* sqlstm,
            otl_connect& db,
            const char* ref_cur_placeholder=0)
        {
            io=0; ss=0; ref_ss=0;
            iov=0; iov_len=0;
            ov=0; ov_len=0;
            auto_commit_flag=1;
            adb=&db;
            open(arr_size,sqlstm,db,ref_cur_placeholder);
        }

        otl_stream()
        {
            ref_ss=0;
            io=0;
            ss=0;
            adb=0;
            ov=0; ov_len=0;
            auto_commit_flag=1;
            iov=0; iov_len=0;
        }

        ~otl_stream()
        {
            close();
        }

        int eof(void)
        {
            if(io)
                return io->eof();
            else if(ss)
                return ss->eof();
            else if(ref_ss)
                return ref_ss->eof();
            else
                return 1;
        }

        void flush(void)
        {
            if(io)io->flush();
        }

        void clean(const int clean_up_error_flag=0)
        {
            if(io)io->clean(clean_up_error_flag);
        }

        void rewind(void)
        {
            if(io)
                io->rewind();
            else if(ss)
                ss->rewind();
            else if(ref_ss)
                ref_ss->rewind();
        }

        int is_null(void)
        {
            if(io)
                return io->is_null();
            else if(ss)
                return ss->is_null();
            else if(ref_ss)
                return ref_ss->is_null();
            else
                return 0;
        }

        void set_commit(int auto_commit=0)
        {
            auto_commit_flag=auto_commit;
            if(io)io->set_commit(auto_commit);
        }

        void open
            (const short arr_size,
            const char* sqlstm,
            otl_connect& db,
            const char* ref_cur_placeholder=0)
        {
            delete[] iov;
            delete[] ov;

            iov=0; iov_len=0;
            ov=0; ov_len=0;

            char tmp[7];
            char* c=(char*)sqlstm;

            while(isspace(*c))++c;
            strncpy(tmp,c,6);
            tmp[6]=0;
            c=tmp;
            while(*c)
            {
                *c=(char)otl_to_upper(*c);
                ++c;
            }
            adb=&db;
            if(strncmp(tmp,"SELECT",6)==0)
            {
                ss=new otl_select_stream(&override,arr_size,sqlstm,db);
            }
            else if(ref_cur_placeholder!=0)
            {
                ref_ss=new otl_ref_select_stream(&override,arr_size,sqlstm,ref_cur_placeholder,db);
            }
            else
            {
                io=new otl_inout_stream(arr_size,sqlstm,db);
            }
            if(io)io->set_commit(auto_commit_flag);
            create_var_desc();
        }

        void close(void)
        {
            delete[] iov;
            delete[] ov;

            iov=0; iov_len=0;
            ov=0; ov_len=0;

            delete ss;
            delete io;
            delete ref_ss;
            ss=0; io=0; ref_ss=0;
            adb=0;
        }

        otl_column_desc* describe_select(int& desc_len)
        {
            desc_len=0;
            if(ss)
            {
                desc_len=ss->sl_len;
                return ss->sl_desc;
            }
            if(ref_ss)
            {
                desc_len=ref_ss->sl_len;
                return ref_ss->sl_desc;
            }
            return 0;
        }

        int good(void)
        {
            if(io||ss||ref_ss)
                return 1;
            else
                return 0;
        }

        otl_stream& operator>>(otl_pl_tab_generic& tab)
        {
            if(io)io->operator>>(tab);
            return *this;
        }

        otl_stream& operator<<(otl_pl_tab_generic& tab)
        {
            if(io)io->operator<<(tab);
            return *this;
        }

        otl_stream& operator>>(char& c)
        {
            if(io)
                io->operator>>(c);
            else if(ss)
                ss->operator>>(c);
            else if(ref_ss)
                ref_ss->operator>>(c);
            return *this;
        }

        otl_stream& operator>>(unsigned char& c)
        {
            if(io)
                io->operator>>(c);
            else if(ss)
                ss->operator>>(c);
            else if(ref_ss)
                ref_ss->operator>>(c);
            return *this;
        }

        otl_stream& operator>>(char* s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator>>(unsigned char* s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator>>(int& n)
        {
            if(io)
                io->operator>>(n);
            else if(ss)
                ss->operator>>(n);
            else if(ref_ss)
                ref_ss->operator>>(n);
            return *this;
        }

        otl_stream& operator>>(unsigned& u)
        {
            if(io)
                io->operator>>(u);
            else if(ss)
                ss->operator>>(u);
            else if(ref_ss)
                ref_ss->operator>>(u);
            return *this;
        }

        otl_stream& operator>>(short& sh)
        {
            if(io)
                io->operator>>(sh);
            else if(ss)
                ss->operator>>(sh);
            else if(ref_ss)
                ref_ss->operator>>(sh);
            return *this;
        }

        otl_stream& operator>>(long int& l)
        {
            if(io)
                io->operator>>(l);
            else if(ss)
                ss->operator>>(l);
            else if(ref_ss)
                ref_ss->operator>>(l);
            return *this;
        }

        otl_stream& operator>>(float& f)
        {
            if(io)
                io->operator>>(f);
            else if(ss)
                ss->operator>>(f);
            else if(ref_ss)
                ref_ss->operator>>(f);
            return *this;
        }

        otl_stream& operator>>(double& d)
        {
            if(io)
                io->operator>>(d);
            else if(ss)
                ss->operator>>(d);
            else if(ref_ss)
                ref_ss->operator>>(d);
            return *this;
        }

        otl_stream& operator>>(otl_long_string& s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator<<(const char c)
        {
            if(io)
                io->operator<<(c);
            else if(ss)
                ss->operator<<(c);
            else if(ref_ss)
            {
                ref_ss->operator<<(c);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const unsigned char c)
        {
            if(io)
                io->operator<<(c);
            else if(ss)
                ss->operator<<(c);
            else if(ref_ss)
            {
                ref_ss->operator<<(c);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const char* s)
        {
            if(io)
                io->operator<<(s);
            else if(ss)
                ss->operator<<(s);
            else if(ref_ss)
            {
                ref_ss->operator<<(s);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const unsigned char* s)
        {
            if(io)
                io->operator<<(s);
            else if(ss)
                ss->operator<<(s);
            else if(ref_ss)
            {
                ref_ss->operator<<(s);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator>>(otl_time0& s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator>>(otl_datetime& s)
        {
            otl_time0 tmp;
            (*this)>>tmp;
            s.year=((int)tmp.century-100)*100+((int)tmp.year-100);
            s.month=tmp.month;
            s.day=tmp.day;
            s.hour=tmp.hour-1;
            s.minute=tmp.minute-1;
            s.second=tmp.second-1;
            return *this;
        }

        otl_stream& operator<<(const int n)
        {
            if(io)
                io->operator<<(n);
            else if(ss)
                ss->operator<<(n);
            else if(ref_ss)
            {
                ref_ss->operator<<(n);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const otl_time0& n)
        {
            if(io)
                io->operator<<(n);
            else if(ss)
                ss->operator<<(n);
            else if(ref_ss)
            {
                ref_ss->operator<<(n);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const otl_datetime& s)
        {
            otl_time0 tmp;
            tmp.year=(s.year%100)+100;
            tmp.century=(s.year/100)+100;
            tmp.month=s.month;
            tmp.day=s.day;
            tmp.hour=s.hour+1;
            tmp.minute=s.minute+1;
            tmp.second=s.second+1;
            (*this)<<tmp;
            return *this;
        }

        otl_stream& operator<<(const unsigned u)
        {
            if(io)
                io->operator<<(u);
            else if(ss)
                ss->operator<<(u);
            else if(ref_ss)
            {
                ref_ss->operator<<(u);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const short sh)
        {
            if(io)
                io->operator<<(sh);
            else if(ss)
                ss->operator<<(sh);
            else if(ref_ss)
            {
                ref_ss->operator<<(sh);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const long int l)
        {
            if(io)
                io->operator<<(l);
            else if(ss)
                ss->operator<<(l);
            else if(ref_ss)
            {
                ref_ss->operator<<(l);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const float f)
        {
            if(io)
                io->operator<<(f);
            else if(ss)
                ss->operator<<(f);
            else if(ref_ss)
            {
                ref_ss->operator<<(f);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const double d)
        {
            if(io)
                io->operator<<(d);
            else if(ss)
                ss->operator<<(d);
            else if(ref_ss)
            {
                ref_ss->operator<<(d);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const otl_null n)
        {
            OTL_UNUSED_ARG(n)
                if(io)io->operator<<(otl_null());
            if(ss)ss->operator<<(otl_null());
            if(ref_ss)
            {
                ref_ss->operator<<(otl_null());
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const otl_long_string& d)
        {
            if(io)io->operator<<(d);
            return *this;
        }

};

typedef otl_tmpl_nocommit_stream<otl_stream,otl_connect> otl_nocommit_stream;

OTL_ORA7_NAMESPACE_END
#endif

// ==================== OTL-Adapter for Oracle 8 =====================
#ifdef OTL_ORA8
#ifdef __STDC__
#define __STDC__DEFINED
#else
#define __STDC__ 1                                // making OCI function prototypes show up in oci.h
#endif
#include <oci.h>

#ifdef OTL_ORA8_PROC
extern "C"
{
    #include <sql2oci.h>
}
#endif

OTL_ORA8_NAMESPACE_BEGIN

const int inVarChar2=1;
const int inNumber=2;
const int inLong=8;
const int inRowId=11;
const int inDate=12;
const int inRaw=23;
const int inLongRaw=24;
const int inChar=96;
const int inMslabel=105;
const int inUserDefinedType=108;
const int inRef=111;
const int inCLOB=112;
const int inBLOB=113;

// Oracle external data types (see Programmer's Guide to the
// Oracle Call Interface, chapter 3)

const int  extVarChar2=1;
const int  extNumber=2;
const int  extInt=3;
const int  extFloat=4;
const int  extCChar=5;
const int  extVarNum=6;
const int  extLong=8;
const int  extVarChar=9;
const int  extRowId=11;
const int  extDate=12;
const int  extVarRaw=15;
const int  extRaw=23;
const int  extLongRaw=24;
const int  extUInt=68;
const int  extLongVarChar=94;
const int  extLongVarRaw=95;
const int  extChar=96;
const int  extCharZ=97;
const int  extMslabel=105;
const int  extCLOB=inCLOB;
const int  extBLOB=inBLOB;

typedef otl_oracle_date otl_time0;

class otl_exc
{
    public:
        unsigned char msg[1000];
        int code;

        char sqlstate[32];

        enum{disabled=0,enabled=1};

        otl_exc()
        {
            sqlstate[0]=0;
        }

        void init(const char* amsg, const int acode)
        {
            strcpy((char*)msg,amsg);
            code=acode;
        }

};

class otl_conn
{
    public:

        OCIEnv *envhp;                            // OCI environment handle
        OCIServer *srvhp;                         // OCI Server handle
        OCIError *errhp;                          // OCI Error handle
        OCISvcCtx *svchp;                         // OCI Service context handle
        OCISession *authp;                        // OCI Session handle
        int auto_commit;
        int extern_lda;
        int attached;
        int in_session;
        int session_begin_count;

        static int initialize(const int threaded_mode=0)
        {
            int status;
            int mode;
            if(threaded_mode)
                mode=OCI_THREADED;
            else
                mode=OCI_DEFAULT;
            status=OCIInitialize
                ((ub4)mode,
                (dvoid *)0,
                (dvoid*(*)(dvoid *,size_t))0,
                (dvoid*(*)(dvoid*,dvoid*,size_t))0,
                (void(*)(dvoid *,dvoid*))0
                );
            if(status!=OCI_SUCCESS)
                return 0;
            else
                return 1;
        }

        otl_conn()
        {
            envhp=0;
            srvhp=0;
            errhp=0;
            svchp=0;
            authp=0;
            auto_commit=0;
            extern_lda=0;
            attached=0;
            in_session=0;
            session_begin_count=0;
        }

        ~otl_conn(){}

        void set_timeout(const int atimeout=0){OTL_UNUSED_ARG(atimeout)}
        void set_cursor_type(const int acursor_type=0){OTL_UNUSED_ARG(acursor_type)}

        int server_attach(const char* tnsname)
        {
            int status;

            envhp=0;
            srvhp=0;
            errhp=0;
            svchp=0;
            authp=0;
            extern_lda=0;
            attached=0;
            in_session=0;
            session_begin_count=0;

            status=OCIEnvInit
                ((OCIEnv **)&envhp,
                OCI_DEFAULT,
                (size_t)0,
                (dvoid **)0);
            if(status)return 0;

            status=OCIHandleAlloc
                ((dvoid*)envhp,
                (dvoid**)&errhp,
                OCI_HTYPE_ERROR,
                (size_t)0,
                (dvoid**)0);
            if(status)return 0;

            status=OCIHandleAlloc
                ((dvoid*)envhp,
                (dvoid**)&srvhp,
                OCI_HTYPE_SERVER,
                (size_t)0,
                (dvoid**)0);
            if(status)return 0;

            status=OCIHandleAlloc
                ((dvoid*)envhp,
                (dvoid**)&svchp,
                OCI_HTYPE_SVCCTX,
                (size_t)0,
                (dvoid**)0);
            if(status)return 0;

            status=OCIServerAttach
                (srvhp,
                errhp,
                tnsname==0?(text*)"":(text*)tnsname,
                tnsname==0?0:strlen((char*)tnsname),
                0);
            if(status)return 0;
            status=OCIAttrSet
                ((dvoid*)svchp,
                OCI_HTYPE_SVCCTX,
                (dvoid*)srvhp,
                (ub4) 0,
                OCI_ATTR_SERVER,
                (OCIError*)errhp);
            if(status)return 0;
            status=OCIHandleAlloc
                ((dvoid*)envhp,
                (dvoid **)&authp,
                (ub4)OCI_HTYPE_SESSION,
                (size_t)0,
                (dvoid**)0);
            if(status)return 0;

            attached=1;
            return 1;

        }

        int session_begin(const int aauto_commit)
        {
            int status;

            if(!attached)return 0;
            if(session_begin_count==0)return 0;

            status=OCISessionBegin
                (svchp,
                errhp,
                authp,
                OCI_CRED_RDBMS,
                (ub4)OCI_DEFAULT);
            if(status)return 0;

            in_session=1;
            auto_commit=aauto_commit;
            ++session_begin_count;
            return 1;

        }

        int session_begin
            (const char* userid,
            const char* password,
            const int aauto_commit)
        {
            int status;

            if(!attached)return 0;

            status=OCIAttrSet
                ((dvoid*)authp,
                (ub4)OCI_HTYPE_SESSION,
                (dvoid*)userid,
                (ub4)strlen((char*)userid),
                (ub4)OCI_ATTR_USERNAME,
                errhp);
            if(status)return 0;

            status=OCIAttrSet
                ((dvoid*)authp,
                (ub4)OCI_HTYPE_SESSION,
                (dvoid*)password,
                (ub4)strlen((char*)password),
                (ub4)OCI_ATTR_PASSWORD,
                errhp);
            if(status)return 0;

            status=OCISessionBegin
                (svchp,
                errhp,
                authp,
                OCI_CRED_RDBMS,
                (ub4)OCI_DEFAULT);
            if(status)return 0;

            status=OCIAttrSet
                ((dvoid*)svchp,
                (ub4)OCI_HTYPE_SVCCTX,
                (dvoid *) authp,
                (ub4)0,
                (ub4)OCI_ATTR_SESSION,
                errhp);
            if(status)return 0;

            in_session=1;
            auto_commit=aauto_commit;
            ++session_begin_count;
            return 1;

        }

        int server_detach(void)
        {
            int status,rc=0;
            if(attached)
            {
                status=OCIServerDetach(srvhp,errhp,(ub4)OCI_DEFAULT);
                rc=1;
            }
            if(srvhp!=0)OCIHandleFree((dvoid *) srvhp, (ub4) OCI_HTYPE_SERVER);
            if(svchp!=0)OCIHandleFree((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX);
            if(errhp!=0)OCIHandleFree((dvoid *) errhp, (ub4) OCI_HTYPE_ERROR);
            if(authp!=0)OCIHandleFree((dvoid *) authp, (ub4) OCI_HTYPE_SESSION);
            if(envhp!=0)OCIHandleFree((dvoid *) envhp, (ub4) OCI_HTYPE_ENV);
            auto_commit=0;
            attached=0;
            in_session=0;
            envhp=0;
            srvhp=0;
            errhp=0;
            svchp=0;
            authp=0;
            return rc;
        }

        int session_end(void)
        {
            int status;
            if(!in_session)return 0;
	    /* modify zhanghua at 2000/10/10 for wrong auto_commit result */
	    if (!auto_commit) rollback();
	    /* modify end */
            status=OCISessionEnd(svchp,errhp,authp,(ub4)0);
            if(status)return 0;

            in_session=0;
            auto_commit=0;
            return 1;
        }

        int rlogon(const char* connect_str,const int aauto_commit)
        {
            int status;
            char username[256];
            char passwd[256];
            char tnsname[256];
            char* tnsname_ptr=0;
            char* c=(char*) connect_str;
            char* username_ptr=username;
            char* passwd_ptr=passwd;

            auto_commit=aauto_commit;

            username[0]=0;
            passwd[0]=0;
            tnsname[0]=0;

            while(*c&&*c!='/')
            {
                *username_ptr=*c;
                ++c;
                ++username_ptr;
            }
            *username_ptr=0;

            if(*c=='/')++c;
            while(*c&&*c!='@')
            {
                *passwd_ptr=*c;
                ++c;
                ++passwd_ptr;
            }
            *passwd_ptr=0;

            if(*c=='@')
            {
                ++c;
                tnsname_ptr=tnsname;
                while(*c)
                {
                    *tnsname_ptr=*c;
                    ++c;
                    ++tnsname_ptr;
                }
                *tnsname_ptr=0;
            }

            envhp=0;
            srvhp=0;
            errhp=0;
            svchp=0;
            authp=0;
            extern_lda=0;
            attached=0;
            in_session=0;

            status=server_attach(tnsname);
            if(!status)return 0;

            status=session_begin(username,passwd,aauto_commit);
            if(!status)return 0;

            return 1;

        }

        int ext_logon(OCIEnv *a_envhp,OCISvcCtx *a_svchp,const int aauto_commit=0)
        {
            int status;

            envhp=a_envhp;
            svchp=a_svchp;
            errhp=0;
            srvhp=0;
            authp=0;
            extern_lda=1;
            auto_commit=aauto_commit;

            status=OCIHandleAlloc
                ((dvoid*)envhp,
                (dvoid**)&errhp,
                OCI_HTYPE_ERROR,
                (size_t)0,
                (dvoid**)0);
            if(status)return 0;

            return 1;

        }

        int logoff(void)
        {   
            if(extern_lda)
            {
                OCIHandleFree((dvoid *) errhp, (ub4) OCI_HTYPE_ERROR);
                envhp=0;
                svchp=0;
                errhp=0;
                extern_lda=0;
            }
            else
            {
                session_end();
                server_detach();
            }
            auto_commit=0;
            return 1;
        }

        void error(otl_exc& exception_struct)
        {
            sb4 errcode;
            int len;
            OCIErrorGet
                ((dvoid*)errhp,
                (ub4)1,
                (text*)NULL,
                &errcode,
                (text*)exception_struct.msg,
                (ub4)sizeof(exception_struct.msg),
                OCI_HTYPE_ERROR);
            exception_struct.code=errcode;
            len=strlen((const char*)exception_struct.msg);
            exception_struct.msg[len]=0;
        }

        int commit(void)
        {
            return !OCITransCommit(svchp,errhp,(ub4)OCI_DEFAULT);
        }

        int rollback(void)
        {
            return !OCITransRollback(svchp,errhp,(ub4)OCI_DEFAULT);
        }

};

class otl_var
{
    public:

        ub1* p_v;
        sb2* p_ind;
        ub2* p_rlen;
        ub2* p_rcode;
        int ftype;
        int array_size;
        int elem_size;
        OCILobLocator** lob;
        otl_conn* connect;
        ub1* buf;
        int buf_len;
        int ext_buf_flag;
        int act_elem_size;
        ub4 max_tab_len;
        ub4 cur_tab_len;
        int pl_tab_flag;
        int lob_stream_flag;

        otl_var()
        {
            lob_stream_flag=0;
            p_v=0;
            p_ind=0;
            p_rlen=0;
            p_rcode=0;
            ftype=0;
            lob=0;
            array_size=0;
            connect=0;
            elem_size=0;
            buf=0;
            buf_len=0;
            ext_buf_flag=0;
            act_elem_size=0;
            max_tab_len=0;
            cur_tab_len=0;
            pl_tab_flag=0;
        }

        ~otl_var()
        {
            int i;
            if(ftype==otl_var_blob||ftype==otl_var_clob&&lob!=0)
            {
                for(i=0;i<array_size;++i)
                    OCIDescriptorFree((dvoid*)lob[i],(ub4)OCI_DTYPE_LOB);
            }
            delete[] p_v;
            delete[] p_ind;
            delete[] p_rlen;
            delete[] p_rcode;
            if(!ext_buf_flag)
                delete[] buf;
        }

        int actual_elem_size(void)
        {
            return act_elem_size;
        }

        void init
            (const int aftype,
            const int aelem_size,
            const short aarray_size,
            const void* connect_struct=0,
            const int apl_tab_flag=0)
        {
            int i;
            ub4 lobEmpty=0;
            int status;

            connect=(otl_conn*)connect_struct;
            ftype=aftype;
            pl_tab_flag=apl_tab_flag;
            act_elem_size=aelem_size;
            if(ftype==otl_var_blob||ftype==otl_var_clob)
            {
                array_size=aarray_size;
                elem_size=aelem_size;
                lob=new OCILobLocator*[array_size];
                p_v=(ub1*)lob;
                p_ind=new sb2[array_size];
                p_rlen=0;
                p_rcode=0;
                connect=(otl_conn*)connect_struct;
                if(connect!=0)
                {
                    for(i=0;i<array_size;++i)
                    {
                        status=OCIDescriptorAlloc
                            ((dvoid*)connect->envhp,
                            (dvoid**)&lob[i],
                            (ub4)OCI_DTYPE_LOB,
                            (size_t)0,
                            (dvoid**)0);
                        lobEmpty=0;
                        status=OCIAttrSet
                            ((dvoid*)lob[i],
                            OCI_DTYPE_LOB,
                            (dvoid*)&lobEmpty,
                            (ub4)0,
                            OCI_ATTR_LOBEMPTY,
                            (OCIError*)connect->errhp);
                    }
                }
                else
                {
                    lob=0;
                }
            }
            else
            {
                if(aftype==otl_var_varchar_long||aftype==otl_var_raw_long)
                {
                    elem_size=aelem_size+sizeof(sb4);
                    array_size=1;
                }
                else
                {
                    elem_size=aelem_size;
                    array_size=aarray_size;
                }
                p_v=new ub1[elem_size*(unsigned)array_size];
                p_ind=new sb2[array_size];
                p_rlen=new ub2[array_size];
                p_rcode=new ub2[array_size];
                memset(p_v,0,elem_size*(unsigned)array_size);
                if(aftype==otl_var_varchar_long||aftype==otl_var_raw_long)
                {
                    if(aelem_size>32767)
                        p_ind[0]=0;
                    else
                        p_ind[0]=(short)aelem_size;
                    p_rcode[0]=0;
                }
                else
                {
                    for(i=0;i<array_size;++i)
                    {
                        p_ind[i]=(short)elem_size;
                        p_rlen[i]=(short)elem_size;
                        p_rcode[i]=0;
                    }
                }
            }
            max_tab_len=(ub4)array_size;
            cur_tab_len=(ub4)0;
        }

        void set_pl_tab_len(const int apl_tab_len)
        {
            max_tab_len=(ub4)array_size;
            cur_tab_len=(ub4)apl_tab_len;
        }

        int get_pl_tab_len(void)
        {
            return (int)cur_tab_len;
        }

        int get_max_pl_tab_len(void)
        {
            return (int)max_tab_len;
        }

        int get_blob_len(const int ndx,int& alen)
        {
            ub4 blen;
            int rc;
            alen=0;
            rc=OCILobGetLength
                (connect->svchp,
                connect->errhp,
                lob[ndx],
                &blen);
            alen=(int)blen;
            if(rc!=0)return 0;
            return 1;
        }

        int get_blob
            (const int ndx,
            unsigned char* abuf,
            const int buf_size,
            int& len)
        {
            ub4 amt=elem_size;
            ub4 offset=1;
            int rc;
            memset((void*)abuf,0,(size_t)buf_size);
            rc=OCILobRead
                (connect->svchp,
                connect->errhp,
                lob[ndx],
                &amt,
                offset,
                (dvoid*)abuf,
                (ub4)elem_size,
                (dvoid*)0,
                (sb4(*)(dvoid*,CONST dvoid*,ub4,ub1))0,
                (ub2)0,
                (ub1)SQLCS_IMPLICIT);
            len=amt;
            if(rc!=0)return 0;
            return 1;
        }

        void set_lob_stream_flag(const int flg=1)
        {
            lob_stream_flag=flg;
        }

        int put_blob(void)
        {
            if(ftype!=otl_var_clob&&ftype!=otl_var_blob||
                lob_stream_flag||buf==0||buf_len==0)return 1;

            ub4 amt=buf_len;
            ub4 offset=1;
            int rc;
            rc=OCILobWrite
                (connect->svchp,
                connect->errhp,
                lob[0],
                &amt,
                offset,
                (dvoid*)buf,
                (ub4)buf_len,
                OCI_ONE_PIECE,
                (dvoid *)0,
                (sb4(*)(dvoid*,dvoid*,ub4*,ub1*))0,
                (ub2)0,
                (ub1)SQLCS_IMPLICIT);
            if(rc!=0)return 0;
            return 1;
        }

        int read_blob
            (otl_long_string& s,
            const int andx,
            int& aoffset,
            int lob_len)
        {
            ub4 amt=0;
            ub4 offset=aoffset;
            int rc;
            rc=OCILobRead
                (connect->svchp,
                connect->errhp,
                lob[andx],
                &amt,
                offset,
                (dvoid*)s.v,
                (ub4)s.buf_size,
                (dvoid*)0,
                (sb4(*)(dvoid*,CONST dvoid*,ub4,ub1))0,
                (ub2)0,
                (ub1)SQLCS_IMPLICIT);
            switch(rc)
            {
                case OCI_SUCCESS:
                    if(aoffset==1)
                        s.set_len(lob_len);
                    else
                        s.set_len(lob_len-aoffset+1);
                    break;
                case OCI_NEED_DATA:
                    s.set_len(s.buf_size);
                    break;
                case OCI_ERROR:
                    s.set_len(0);
                    break;
            }
            if(rc==OCI_NEED_DATA||rc==OCI_SUCCESS)
            {
                aoffset+=s.length;
                return 1;
            }else
            return 0;
        }

        int write_blob
            (const otl_long_string& s,
            const int lob_len,
            int& aoffset)
        {
            if(!lob_stream_flag)return 1;
            if(lob_len==0)return 1;

            ub4 offset=(ub4)aoffset;
            ub4 amt=lob_len;
            int rc;
            ub1 mode;
            if(aoffset==1&&lob_len>s.length)
                mode=OCI_FIRST_PIECE;
            else if(aoffset==1&&lob_len<=s.length)
            {
                mode=OCI_ONE_PIECE;
                amt=s.length;
            }else if((aoffset-1)+s.length<lob_len)
            mode=OCI_NEXT_PIECE;
            else
                mode=OCI_LAST_PIECE;
            rc=OCILobWrite
                (connect->svchp,
                connect->errhp,
                lob[0],
                (ub4*)&amt,
                offset,
                (dvoid*)s.v,
                (ub4)s.length,
                mode,
                (dvoid *)0,
                (sb4(*)(dvoid*,dvoid*,ub4*,ub1*))0,
                (ub2)0,
                (ub1)SQLCS_IMPLICIT);
            if(rc==OCI_NEED_DATA||
                rc==OCI_SUCCESS||
                rc==OCI_SUCCESS_WITH_INFO)
            {
                aoffset+=s.length;
                return 1;
            }
            return 0;
        }

        int save_blob
            (const unsigned char* abuf,
            const int len,
            const int extern_buffer_flag)
        {
            if(extern_buffer_flag)
            {
                ext_buf_flag=1;
                buf_len=len;
                buf=(unsigned char*)abuf;
            }
            else
            {
                if(buf!=0&&!ext_buf_flag)
                {
                    delete[] buf;
                    buf=0;
                }
                ext_buf_flag=0;
                buf_len=len;
                buf=new ub1[buf_len];
                memcpy(buf,abuf,buf_len);
            }
            return 1;
        }

        void set_null(int ndx)
        {
            p_ind[ndx]=-1;
        }

        void set_not_null(int ndx, int pelem_size)
        {
            if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
                p_ind[0]=0;
            else if(ftype==otl_var_clob||ftype==otl_var_blob)
            {
                if(lob_stream_flag==0)
                {
                    ub4 lobEmpty=0;
                    int status;
                    status=OCIAttrSet
                        ((dvoid*)lob[ndx],
                        OCI_DTYPE_LOB,
                        (dvoid*)&lobEmpty,
                        (ub4)0,
                        OCI_ATTR_LOBEMPTY,
                        (OCIError*)connect->errhp);
                }
            }else
            p_ind[ndx]=(short)pelem_size;
        }

        void set_len(int len, int ndx)
        {
            if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
                *(sb4*)p_v=len;
            else
                p_rlen[ndx]=(short)len;
        }

        int get_len(int ndx)
        {
            if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
            {
                if(p_ind[0]==-1)
                    return 0;
                else
                    return *(sb4*)p_v;
            }else
            return p_rlen[ndx];
        }

        int is_null(int ndx)
        {
            return p_ind[ndx]==-1;
        }

        void* val(int ndx,int pelem_size)
        {
            if(ftype==otl_var_varchar_long||ftype==otl_var_raw_long)
                return (void*)(p_v+sizeof(sb4));
            else
                return (void*)&p_v[((unsigned)ndx)*pelem_size];
        }

        static int int2ext(int int_type)
        {
            switch(int_type)
            {
                case inVarChar2: return extCChar;
                case inNumber:   return extFloat;
                case inLong:     return extLongVarChar;
                case inRowId:    return extCChar;
                case inDate:     return extDate;
                case inRaw:      return extCChar;
                case inLongRaw:  return extLongVarRaw;
                case inChar:     return extCChar;
                case inCLOB:     return extCLOB;
                case inBLOB:     return extBLOB;
                default:
                    return -1;
            }
        }

        static int datatype_size(int ftype,int maxsz,int int_type,int max_long_size)
        {
            switch(ftype)
            {
                case extCChar:
                    switch(int_type)
                    {
                        case inRowId:
                            return 30;
                        case inDate:
                            return otl_oracle_date_size;
                        case inRaw:
                            return maxsz*2+1;
                        default:
                            return maxsz+1;
                    }
                case extLongVarChar:
                    return max_long_size;
                case extLongVarRaw:
                    return max_long_size;
                case extCLOB:
                    return max_long_size;
                case extBLOB:
                    return max_long_size;
                case extFloat:
                    return sizeof(double);
                case extDate:
                    return otl_oracle_date_size;
                default:
                    return 0;
            }
        }

        static void map_ftype
            (otl_column_desc& desc,
            const int max_long_size,
            int& ftype,
            int& elem_size,
            otl_select_struct_override& override,
            const int column_ndx)
        {
            int ndx=override.find(column_ndx);
            if(ndx==-1)
            {
                ftype=int2ext(desc.dbtype);
                elem_size=datatype_size(ftype,desc.dbsize,desc.dbtype,max_long_size);
                switch(ftype)
                {
                    case extCChar:
                        ftype=otl_var_char;
                        break;
                    case extFloat:
                        ftype=otl_var_double;
                        break;
                    case extLongVarChar:
                        ftype=otl_var_varchar_long;
                        break;
                    case extLongVarRaw:
                        ftype=otl_var_raw_long;
                        break;
                    case extCLOB:
                        ftype=otl_var_clob;
                        break;
                    case extBLOB:
                        ftype=otl_var_blob;
                        break;
                    case extDate:
                        ftype=otl_var_timestamp;
                        break;
                }
            }
            else
            {
                ftype=override.col_type[ndx];
                switch(ftype)
                {
                    case otl_var_char:
                        elem_size=override.col_size[ndx];
                        break;
                    case otl_var_double:
                        elem_size=sizeof(double);
                        break;
                    case otl_var_float:
                        elem_size=sizeof(float);
                        break;
                    case otl_var_int:
                        elem_size=sizeof(int);
                        break;
                    case otl_var_unsigned_int:
                        elem_size=sizeof(unsigned);
                        break;
                    case otl_var_short:
                        elem_size=sizeof(short);
                        break;
                    case otl_var_long_int:
                        elem_size=sizeof(double);
                        break;
                    default:
                        elem_size=override.col_size[ndx];
                        break;
                }
            }
            desc.otl_var_dbtype=ftype;
        }

};

class otl_cur
{
    public:

        OCIStmt* cda;                             // Statement handle
        OCIError* errhp;                          // Error handle
        int status;
        int eof_status;
        otl_conn* db;
        int straight_select;
        int pos_nbr;
        int commit_on_success;

        otl_cur()
        {
            cda=0;
            errhp=0;
            db=0;
            straight_select=1;
            pos_nbr=0;
            commit_on_success=0;
        }

        ~otl_cur(){}

        void set_direct_exec(const int flag){OTL_UNUSED_ARG(flag)}

        ub4 rpc(void)
        {
            sb4 rpc;
            status=OCIAttrGet
                ((dvoid *)cda,
                (ub4)OCI_HTYPE_STMT,
                (dvoid *) &rpc,
                (ub4 *) 0,
                (ub4)OCI_ATTR_ROW_COUNT,
                errhp);
            if(status)return 0;
            return rpc;
        }

        int open(otl_conn& connect)
        {
            db=&connect;
            commit_on_success=db->auto_commit;
            status=OCIHandleAlloc
                ((dvoid *) db->envhp,
                (dvoid **) &cda,
                OCI_HTYPE_STMT,
                (size_t)0,
                (dvoid **) 0);
            if(status)return 0;
            status=OCIHandleAlloc
                ((dvoid *) db->envhp,
                (dvoid **) &errhp,
                OCI_HTYPE_ERROR,
                (size_t) 0,
                (dvoid **) 0);
            if(status)return 0;
            straight_select=1;
            pos_nbr=0;
            return 1;
        }

        int close(void)
        {
            status=OCIHandleFree((dvoid *) cda, OCI_HTYPE_STMT);
            status=OCIHandleFree((dvoid *) errhp, OCI_HTYPE_ERROR);
            cda=0;
            errhp=0;
            commit_on_success=0;
            return 1;
        }

        int parse(const char* stm_text)
        {
            status=OCIStmtPrepare
                (cda,
                errhp,
                (text*)stm_text,
                (ub4) strlen(stm_text),
                (ub4) OCI_NTV_SYNTAX,
                (ub4) OCI_DEFAULT);
            if(status)return 0;
            return 1;
        }

        int exec(const int iters)
        {
            ub4 mode;
            if(commit_on_success)
                mode=OCI_COMMIT_ON_SUCCESS;
            else
                mode=OCI_DEFAULT;
            status=OCIStmtExecute
                (db->svchp,
                cda,
                errhp,
                (ub4) iters,
                (ub4) 0,
                (OCISnapshot *) NULL,
                (OCISnapshot *) NULL,
                mode);
            if(status!=OCI_SUCCESS&&
                status!=OCI_SUCCESS_WITH_INFO)
                return 0;
            return 1;
        }

        long get_rpc()
        {
            return rpc();
        }

        int fetch(const short iters,int& eof_data)
        {
            eof_data=0;
            status=OCIStmtFetch
                (cda,
                errhp,
                (ub4) iters,
                (ub4) OCI_FETCH_NEXT,
                (ub4) OCI_DEFAULT);
            eof_status=status;
            if(status!=OCI_SUCCESS&&
                status!=OCI_SUCCESS_WITH_INFO&&
                status!=OCI_NO_DATA)
                return 0;
            if(status==OCI_NO_DATA)
            {
                eof_data=1;
                return 1;
            }
            return 1;
        }

        int tmpl_ftype2ora_ftype(const int ftype)
        {
            switch(ftype)
            {
                case otl_var_char:
                    return extCChar;
                case otl_var_double:
                    return extFloat;
                case otl_var_float:
                    return extFloat;
                case otl_var_int:
                    return extInt;
                case otl_var_unsigned_int:
                    return extUInt;
                case otl_var_short:
                    return extInt;
                case otl_var_long_int:
                    return extInt;
                case otl_var_timestamp:
                    return extDate;
                case otl_var_varchar_long:
                    return extLongVarChar;
                case otl_var_raw_long:
                    return extLongVarRaw;
                case otl_var_clob:
                    return SQLT_CLOB;
                case otl_var_blob:
                    return SQLT_BLOB;
                default:
                    return 0;
            }
        }

        int bind
            (const char* name,
            otl_var& v,
            const int elem_size,
            const int ftype,
            const int param_type,
            const int name_pos,
            const int apl_tab_flag)
        {
            OCIBind* bindpp;

            OTL_UNUSED_ARG(name_pos)
                OTL_UNUSED_ARG(param_type)

                if(ftype!=otl_var_clob&&
                ftype!=otl_var_blob)
            {
                if(apl_tab_flag)
                    status=OCIBindByName
                        (cda,
                        &bindpp,
                        errhp,
                        (text*) name,
                        strlen(name),
                        (dvoid*)v.p_v,
                        elem_size,
                        (ub2)tmpl_ftype2ora_ftype(ftype),
                        (dvoid*)v.p_ind,
                        (ub2*) 0,
                        (ub2*) 0,
                        (ub4)v.max_tab_len,
                        (ub4*)&v.cur_tab_len,
                        OCI_DEFAULT);
                else
                    status=OCIBindByName
                        (cda,
                        &bindpp,
                        errhp,
                        (text*) name,
                        strlen(name),
                        (dvoid*)v.p_v,
                        elem_size,
                        (ub2)tmpl_ftype2ora_ftype(ftype),
                        (dvoid*)v.p_ind,
                        (ub2*) 0,
                        (ub2*) 0,
                        (ub4) 0,
                        (ub4*) 0,
                        OCI_DEFAULT);
                if(status)return 0;
                return 1;
            }
            else
            {
                status=OCIBindByName
                    (cda,
                    &bindpp,
                    errhp,
                    (text*) name,
                    strlen(name),
                    (dvoid*)v.p_v,
                    (sb4)-1,
                    (ub2)tmpl_ftype2ora_ftype(ftype),
                    (dvoid*)v.p_ind,
                    (ub2*) 0,
                    (ub2*) 0,
                    (ub4) 0,
                    (ub4*) 0,
                    OCI_DEFAULT);
                if(status)return 0;
                return 1;
            }
        }

        int bind
            (const int column_num,
            otl_var& v,
            const int elem_size,
            const int ftype,
            const int param_type)
        {
            OCIDefine *defnp;

            OTL_UNUSED_ARG(param_type)

                if(ftype!=otl_var_clob&&ftype!=otl_var_blob)
            {
                status=OCIDefineByPos
                    (cda,
                    &defnp,
                    errhp,
                    (ub4)column_num,
                    (dvoid*)v.p_v,
                    (sb4)elem_size,
                    (ub2)tmpl_ftype2ora_ftype(ftype),
                    (dvoid*)v.p_ind,
                    (ub2*)v.p_rlen,
                    (ub2*)v.p_rcode,
                    OCI_DEFAULT);
                if(status)return 0;
                return 1;
            }
            else
            {
                status=OCIDefineByPos
                    (cda,
                    &defnp,
                    errhp,
                    (ub4)column_num,
                    (dvoid*)v.p_v,
                    (sb4)-1,
                    (ub2)tmpl_ftype2ora_ftype(ftype),
                    (dvoid*)v.p_ind,
                    (ub2*)v.p_rlen,
                    (ub2*)v.p_rcode,
                    OCI_DEFAULT);
                if(status)return 0;
                return 1;
            }
        }

        void set_select_type(const int select_type)
        {
            straight_select=select_type;
        }

        int describe_column
            (otl_column_desc& col,
            const int column_num,
            int& eof_desc)
        {
            OCIParam* pard;
            ub2 dtype;
            ub2 dbsize;
            sb2 prec;

        #ifdef OTL_ORA8_8I_DESC_COLUMN_SCALE
            ub1 scale;
        #else
            sb2 scale;
        #endif

            ub1 nullok;
            text* col_name;
            ub4 col_name_len;
            ub4 pos_num;

            eof_desc=0;
            if(straight_select&&pos_nbr==0)
            {
                status=OCIStmtExecute
                    (db->svchp,
                    cda,
                    errhp,
                    (ub4) 0,
                    (ub4) 0,
                    (OCISnapshot *) NULL,
                    (OCISnapshot *) NULL,
                    OCI_DESCRIBE_ONLY);
                if(status!=OCI_SUCCESS)return 0;
                status=OCIAttrGet
                    (cda,
                    OCI_HTYPE_STMT,
                    (ub4*)&pos_num,
                    (ub4*) 0,
                    (ub4) OCI_ATTR_PARAM_COUNT,
                    errhp);
                if(status!=OCI_SUCCESS)return 0;
                pos_nbr=(int)pos_num;
            }
            if(!straight_select&&pos_nbr==0)
            {
                status=OCIAttrGet
                    (cda,
                    OCI_HTYPE_STMT,
                    (ub4*)&pos_num,
                    (ub4*) 0,
                    (ub4) OCI_ATTR_PARAM_COUNT,
                    errhp);
                if(status!=OCI_SUCCESS)return 0;
                pos_nbr=(int)pos_num;
            }
            if(column_num<1||column_num>pos_nbr)
            {
                eof_desc=1;
                return 0;
            }
            status=OCIParamGet
                (cda,
                OCI_HTYPE_STMT,
                errhp,
                (void**) &pard,
                (ub4) column_num);
            if(status!=OCI_SUCCESS&&status!=OCI_NO_DATA)
                return 0;
            if(status==OCI_NO_DATA)
            {
                eof_desc=1;
                return 1;
            }
            status=OCIAttrGet
                ((dvoid*)pard,
                (ub4) OCI_DTYPE_PARAM,
                (dvoid*) &dtype,
                (ub4 *) 0,
                (ub4) OCI_ATTR_DATA_TYPE,
                (OCIError *) errhp);
            if(status!=OCI_SUCCESS)return 0;
            col.dbtype=dtype;
            status=OCIAttrGet
                ((dvoid*) pard,
                (ub4) OCI_DTYPE_PARAM,
                (dvoid**)&col_name,
                (ub4*)&col_name_len,
                (ub4) OCI_ATTR_NAME,
                (OCIError *) errhp);
            if(status!=OCI_SUCCESS)return 0;
            strncpy((char*)col.name,(char*)col_name,sizeof(col.name));
            col.name[sizeof(col.name)-1]=0;
            col.name[col_name_len]=0;
            status=OCIAttrGet
                ((dvoid*)pard,
                (ub4) OCI_DTYPE_PARAM,
                (dvoid*) &dbsize,
                (ub4 *) 0,
                (ub4) OCI_ATTR_DATA_SIZE,
                (OCIError *) errhp);
            if(status!=OCI_SUCCESS)return 0;
            col.dbsize=dbsize;
            status=OCIAttrGet
                ((dvoid*)pard,
                (ub4) OCI_DTYPE_PARAM,
                (dvoid*) &prec,
                (ub4 *) 0,
                (ub4) OCI_ATTR_PRECISION,
                (OCIError *) errhp);
            if(status!=OCI_SUCCESS)return 0;
            col.prec=prec;
            status=OCIAttrGet
                ((dvoid*)pard,
                (ub4) OCI_DTYPE_PARAM,
                (dvoid*) &scale,
                (ub4 *) 0,
                (ub4) OCI_ATTR_SCALE,
                (OCIError *) errhp);
            if(status!=OCI_SUCCESS)return 0;
            col.scale=scale;
            status=OCIAttrGet
                ((dvoid*)pard,
                (ub4) OCI_DTYPE_PARAM,
                (dvoid*) &nullok,
                (ub4 *) 0,
                (ub4) OCI_ATTR_IS_NULL,
                (OCIError *) errhp);
            if(status!=OCI_SUCCESS)return 0;
            col.nullok=nullok;
            return 1;
        }

        void error(otl_exc& exception_struct)
        {
            sb4 errcode;
            int len;
            int rc;
            strcpy((char*)exception_struct.msg,"123456789");
            rc=OCIErrorGet
                ((dvoid*)errhp,
                (ub4)1,
                (text*)NULL,
                &errcode,
                (text*)exception_struct.msg,
                (ub4)sizeof(exception_struct.msg),
                OCI_HTYPE_ERROR);
            exception_struct.code=errcode;
            len=strlen((const char*)exception_struct.msg);
            exception_struct.msg[len]=0;
        }

};

class otl_sel
{
    public:

        int implicit_cursor;

        otl_sel()
        {
            implicit_cursor=0;
        }

        ~otl_sel(){}

        void set_select_type(const int atype)
        {
            OTL_UNUSED_ARG(atype)
                implicit_cursor=0;
        }

        void init(const int array_size){OTL_UNUSED_ARG(array_size)}

        int first
            (otl_cur& cur,
            int& cur_row,
            int& cur_size,
            int& row_count,
            int& eof_data,
            const int array_size)
        {
            int rc;
            eof_data=0;
            cur_row=-1;
            cur.commit_on_success=0;
            rc=cur.exec(0);
            if(rc==0)return 0;
            rc=cur.fetch((short)array_size,eof_data
                );
            if(rc==0)return 0;
            row_count=cur.rpc();
            cur_size=row_count;
            if(cur_size!=0)cur_row=0;
            return 1;
        }

        int next
            (otl_cur& cur,
            int& cur_row,
            int& cur_size,
            int& row_count,
            int& eof_data,
            const int array_size)
        {
            int rc;
            if(cur_row<cur_size-1)
            {
                ++cur_row;
                return 1;
            }
            else
            {
                if(eof_data)
                {
                    cur_row=-1;
                    cur_size=0;
                    return 1;
                }
                cur.commit_on_success=0;
                rc=cur.fetch((short)array_size,eof_data);
                if(rc==0)return 0;
                cur_size=cur.rpc()-row_count;
                row_count=cur.rpc();
                if(cur_size!=0)cur_row=0;
                return 1;
            }
        }

};

typedef otl_tmpl_connect
<otl_exc,
otl_conn,
otl_cur> otl_ora8_connect;

typedef otl_tmpl_cursor
<otl_exc,
otl_conn,
otl_cur,
otl_var> otl_cursor;

typedef otl_tmpl_lob_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var> otl_lob_stream;

typedef otl_tmpl_exception
<otl_exc,
otl_conn,
otl_cur> otl_exception;

typedef otl_tmpl_inout_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var,
otl_time0> otl_inout_stream;

typedef otl_tmpl_select_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var,
otl_sel,
otl_time0> otl_select_stream;

typedef otl_tmpl_basic_stream
<otl_exc,
otl_conn,
otl_cur,
otl_var,
otl_sel,
otl_time0> otl_basic_stream;

typedef otl_tmpl_ext_hv_decl
<otl_var,
otl_time0,
otl_exc,
otl_conn,
otl_cur> otl_ext_hv_decl;

class otl_connect: public otl_ora8_connect
{
    public:

        otl_connect():otl_ora8_connect(){}
        otl_connect(const char* connect_str, const int aauto_commit=0)
            : otl_ora8_connect(connect_str, aauto_commit){}

        ~otl_connect(){}

        void rlogon(OCIEnv *envhp,OCISvcCtx *svchp)
        {
            connected=0;
            long_max_size=32760;
            retcode=connect_struct.ext_logon(envhp,svchp,0);
            if(retcode)
                connected=1;
            else
            {
                connected=0;
                throw otl_exception(connect_struct);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
        }

        void rlogon(const char* connect_str, const int aauto_commit=0)
        {
            otl_ora8_connect::rlogon(connect_str,aauto_commit);
        }

        void logoff(void)
        {
            if(!connected)
            {
                connect_struct.session_end();
                connect_struct.server_detach();
            }
            else
            {
                retcode=connect_struct.logoff();
                connected=0;
                if(retcode)
                    return;
                else
                    throw otl_exception(connect_struct);
            }
        }

        void server_attach(const char* tnsname=0)
        {
            connected=0;
            long_max_size=32760;
            retcode=connect_struct.server_attach(tnsname);
            if(!retcode)
            {
                throw otl_exception(connect_struct);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
        }

        void server_detach(void)
        {
            retcode=connect_struct.server_detach();
            if(!retcode)
            {
                throw otl_exception(connect_struct);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
        }

        void session_begin
            (const char* username,
            const char* password,
            const int auto_commit=0)
        {
            retcode=connect_struct.session_begin(username,password,auto_commit);
            if(retcode)
                connected=1;
            else
            {
                connected=0;
                throw otl_exception(connect_struct);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
        }

        void session_reopen(const int auto_commit=0)
        {
            if(connect_struct.session_begin_count==0)
            {
                connected=0;
                throw otl_exception(otl_error_msg_11,otl_error_code_11);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
            retcode=connect_struct.session_begin(auto_commit);
            if(retcode)
                connected=1;
            else
            {
                connected=0;
                throw otl_exception(connect_struct);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
        }

        void session_end(void)
        {
            connected=0;
            retcode=connect_struct.session_end();
            if(!retcode)
            {
                throw otl_exception(connect_struct);
            #ifndef __SUNPRO_CC
                return;
            #endif
            }
        }

};

// ============ OTL Reference Cursor Streams for Oracle 8 =================

typedef otl_tmpl_variable<otl_var> otl_generic_variable;
typedef otl_generic_variable* otl_p_generic_variable;

class otl_ref_cursor: public
otl_tmpl_cursor
<otl_exc,
otl_conn,
otl_cur,
otl_var>
{
    public:

        int cur_row;
        int cur_size;
        int row_count;
        int array_size;

        otl_ref_cursor
            (otl_connect& db,
            const char* cur_placeholder_name,
            const short arr_size=1)
            :otl_tmpl_cursor
            <otl_exc,
            otl_conn,
            otl_cur,
            otl_var>(db)
        {
            int i;
            cur_row=-1;
            row_count=0;
            cur_size=0;
            array_size=arr_size;
            rvl_len=otl_var_list_size;
            vl_cur_len=0;
            rvl=new otl_p_generic_variable[rvl_len];
            for(i=0;i<rvl_len;++i)rvl[i]=0;
            strcpy(cur_placeholder,cur_placeholder_name);
        }

        otl_ref_cursor():
        otl_tmpl_cursor
            <otl_exc,
            otl_conn,
            otl_cur,
            otl_var>(),
            sel_cur()
        {
        }

        ~otl_ref_cursor()
        {
            delete[] rvl;
            rvl=0;
        }

        void open
            (otl_connect& db,
            const char* cur_placeholder_name,
            const short arr_size=1)
        {
            int i;
            cur_row=-1;
            row_count=0;
            cur_size=0;
            array_size=arr_size;
            rvl_len=otl_var_list_size;
            vl_cur_len=0;
            rvl=new otl_p_generic_variable[rvl_len];
            for(i=0;i<rvl_len;++i)rvl[i]=0;
            strcpy(cur_placeholder,cur_placeholder_name);
            if(!sel_cur.connected)sel_cur.open(db);
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::open(db);
        }

        void release_sel_cur(void)
        {
        #ifdef OTL_ORA8_8I_REFCUR
            return;
        #else
            char tmp_buf[256];
            OCIBind* bindpp;
            int rc;

            if(!sel_cur.connected)return;
            strcpy(tmp_buf,"begin close ");
            strcat(tmp_buf,cur_placeholder);
            strcat(tmp_buf,"; end;");
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::parse(tmp_buf);
            rc=OCIBindByName
                (cursor_struct.cda,
                &bindpp,
                cursor_struct.errhp,
                (text*)cur_placeholder,
                strlen(cur_placeholder),
                (dvoid*)&sel_cur.cursor_struct.cda,
                0,
                SQLT_RSET,
                (dvoid*)0,
                (ub2*) 0,
                (ub2*) 0,
                (ub4) 0,
                (ub4*) 0,
                OCI_DEFAULT);
            if(rc!=0)throw otl_exception(cursor_struct,stm_text);
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::exec();
        #endif
        }

        void close(void)
        {
            delete[] rvl;
            rvl=0;
            release_sel_cur();
            sel_cur.close();
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::close();
        }

        int first(void)
        {
            int i,rc;
            OCIBind* bindpp;

            if(!sel_cur.connected)
            {
                sel_cur.open(*adb);
                rc=OCIBindByName
                    (cursor_struct.cda,
                    &bindpp,
                    cursor_struct.errhp,
                    (text*)cur_placeholder,
                    strlen(cur_placeholder),
                    (dvoid*)&sel_cur.cursor_struct.cda,
                    0,
                    SQLT_RSET,
                    (dvoid*)0,
                    (ub2*) 0,
                    (ub2*) 0,
                    (ub4) 0,
                    (ub4*) 0,
                    OCI_DEFAULT);
                if(rc!=0)throw otl_exception(cursor_struct,stm_text);
            }

            if(cur_row==-2)
                ;                                 // Special case -- calling describe_select() between parse() and first()
            else
            {
                exec(1);                          // Executing the PLSQL master block
                sel_cur.connected=1;
            }
            cur_row=-1;
            for(i=0;i<vl_cur_len;++i)
                sel_cur.bind(i+1,*rvl[i]);
            rc=sel_cur.cursor_struct.fetch((short)array_size,sel_cur.eof_data);
            if(rc==0)throw otl_exception(sel_cur.cursor_struct,stm_text);
            row_count=sel_cur.cursor_struct.rpc();
            cur_size=row_count;
            if(cur_size!=0)cur_row=0;
            return cur_size!=0;
        }

        int next(void)
        {
            int rc;
            if(cur_row<0)return first();
            if(cur_row<cur_size-1)
                ++cur_row;
            else
            {
                if(sel_cur.eof())
                {
                    cur_row=-1;
                    return 0;
                }
                rc=sel_cur.cursor_struct.fetch((short)array_size,sel_cur.eof_data);
                if(rc==0)throw otl_exception(sel_cur.cursor_struct,stm_text);
                cur_size=sel_cur.cursor_struct.rpc()-row_count;
                row_count=sel_cur.cursor_struct.rpc();
                if(cur_size!=0)cur_row=0;
            }
            return cur_size!=0;
        }

        void bind
            (const int column_num,
            otl_generic_variable& v)
        {
            if(!connected)return;
            ++vl_cur_len;
            rvl[vl_cur_len-1]=&v;
            v.pos=column_num;
        }

        void bind(otl_generic_variable& v)
        {
            if(v.pos)
                bind(v.pos,v);
            else if(v.name)
                otl_tmpl_cursor
                        <otl_exc,
                        otl_conn,
                        otl_cur,
                        otl_var>::bind(v);
        }

        void bind
            (const char* name,
            otl_generic_variable& v)
        {
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::bind(name,v);
        }

        int describe_select
            (otl_column_desc* desc,
            int& desc_len)
        {
            int i,rc;
            OCIBind* bindpp;

            if(!sel_cur.connected)
            {
                sel_cur.open(*adb);
                rc=OCIBindByName
                    (cursor_struct.cda,
                    &bindpp,
                    cursor_struct.errhp,
                    (text*)cur_placeholder,
                    strlen(cur_placeholder),
                    (dvoid*)&sel_cur.cursor_struct.cda,
                    0,
                    SQLT_RSET,
                    (dvoid*)0,
                    (ub2*) 0,
                    (ub2*) 0,
                    (ub4) 0,
                    (ub4*) 0,
                    OCI_DEFAULT);
                if(rc!=0)throw otl_exception(cursor_struct,stm_text);
            }
            exec(1);                              // Executing the PLSQL master block
            sel_cur.connected=1;
            cur_row=-2;                           // Special case -- describe_select() before first() or next()
            desc_len=0;
            sel_cur.cursor_struct.straight_select=0;
            for(i=1;sel_cur.describe_column(desc[i-1],i);++i)
                ++desc_len;
            return 1;
        }

    protected:

        int rvl_len;
        otl_p_generic_variable* rvl;
        int vl_cur_len;
        otl_cursor sel_cur;
        char cur_placeholder[64];

};

class otl_ref_select_stream: public otl_ref_cursor
{
    public:

        otl_select_struct_override *override;

        void cleanup(void)
        {
            int i;
            delete[] sl;
            for(i=0;i<vl_len;++i)
                delete vl[i];
            delete[] vl;
            delete[] sl_desc;
        }

        otl_ref_select_stream
            (otl_select_struct_override* aoverride,
            const short arr_size,
            const char* sqlstm,
            const char* param_cur_placeholder,
            otl_connect& db)
            :otl_ref_cursor(db,param_cur_placeholder,arr_size)
        {
            init();

            override=aoverride;
            {
                int len=strlen(sqlstm)+1;
                stm_text=new char[len];
                strcpy(stm_text,sqlstm);
                otl_ext_hv_decl hvd(stm_text,1);
                hvd.alloc_host_var_list(vl,vl_len,*adb);
            }

            try
            {

                parse();
                if(vl_len==0)
                {
                    rewind();
                    null_fetched=0;
                }
            }
            catch(otl_exception)
            {
                cleanup();
                throw;
            }

        }

        ~otl_ref_select_stream()
        {
            cleanup();
            close();
        }

        void rewind(void)
        {
            get_select_list();
            ret_code=first();
            null_fetched=0;
            cur_col=-1;
            cur_in=0;
            executed=1;
        }

        int is_null(void)
        {
            return null_fetched;
        }

        int eof(void)
        {
            return !ret_code;
        }

        otl_ref_select_stream& operator>>(otl_time0& t)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_timestamp)&&!eof())
            {
                otl_time0* tm=(otl_time0*)sl[cur_col].val(cur_row);
                memcpy((void*)&t,tm,otl_oracle_date_size);
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator<<(const otl_time0& t)
        {
            check_in_var();
            if(check_in_type(otl_var_timestamp,otl_oracle_date_size))
            {
                otl_time0* tm=(otl_time0*)vl[cur_in]->val();
                memcpy(tm,(void*)&t,otl_oracle_date_size);
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator>>(char& c)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                c=*(char*)sl[cur_col].val(cur_row);
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(unsigned char& c)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                c=*(unsigned char*)sl[cur_col].val(cur_row);
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(char* s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                strcpy((char*)s,(char*)sl[cur_col].val(cur_row));
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(unsigned char* s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(check_type(otl_var_char)&&!eof())
            {
                strcpy((char*)s,(char*)sl[cur_col].val(cur_row));
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(int& n)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_int
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    n);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_int))
                        n=(int)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(unsigned& u)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_unsigned
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    u);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_unsigned_int))
                        u=(unsigned)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(short& sh)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_short
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    sh);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_short))
                        sh=(short)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(long int& l)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_long_int
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    l);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_long_int))
                        l=(long int)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(float& f)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_float
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    f);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_float))
                        f=(float)*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(double& d)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if(!eof())
            {
                int match_found=otl_numeric_convert_double
                    (sl[cur_col].ftype,
                    sl[cur_col].val(cur_row),
                    d);
                if(!match_found)
                {
                    if(check_type(otl_var_double,otl_var_double))
                        d=*(double*)sl[cur_col].val(cur_row);
                }
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(otl_long_string& s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if((sl[cur_col].ftype==otl_var_varchar_long||
                sl[cur_col].ftype==otl_var_raw_long)&&
                !eof())
            {
                unsigned char* c=(unsigned char*)sl[cur_col].val(cur_row);
                int len=sl[cur_col].get_len(cur_row);
                if(len>s.buf_size)len=s.buf_size;
                memcpy(s.v,c,len);
                s.v[len]=0;
                s.set_len(len);
                look_ahead();
            }else if((sl[cur_col].ftype==otl_var_blob||
                sl[cur_col].ftype==otl_var_clob)&&
                !eof())
            {
                int len;
                int rc=sl[cur_col].var_struct.get_blob(cur_row,s.v,s.buf_size,len);
                if(rc==0)
                    throw otl_exception(adb->connect_struct,stm_text);
                s.set_len(len);
                s.v[len]=0;
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator>>(otl_lob_stream& s)
        {
            check_if_executed();
            if(eof())return *this;
            get_next();
            if((sl[cur_col].ftype==otl_var_blob||
                sl[cur_col].ftype==otl_var_clob)&&
                !eof())
            {
                s.init
                    (&sl[cur_col],
                    adb,
                    (otl_ref_cursor*)this,
                    cur_row,
                    otl_lob_stream_read_mode);
                look_ahead();
            }
            return *this;
        }

        otl_ref_select_stream& operator<<(const otl_null n)
        {
            OTL_UNUSED_ARG(n)
                check_in_var();
            vl[cur_in]->set_null(0);
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const char c)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {
                char* tmp=(char*)vl[cur_in]->val();
                tmp[0]=c;
                tmp[1]=0;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const unsigned char c)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {
                unsigned char* tmp=(unsigned char*)vl[cur_in]->val();
                tmp[0]=c;
                tmp[1]=0;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const char* s)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {

                int overflow;
                otl_strcpy
                    ((unsigned char*)vl[cur_in]->val(),
                    (unsigned char*)s,
                    overflow,
                    vl[cur_in]->elem_size
                    );
                if(overflow)
                {
                    char l_var_info[256];
                    otl_var_info_var
                        (vl[cur_in]->name,
                        vl[cur_in]->ftype,
                        otl_var_char,
                        l_var_info);
                    throw otl_exception
                        (otl_error_msg_4,
                        otl_error_code_4,
                        stm_text,
                        l_var_info);
                #ifndef __SUNPRO_CC
                    return *this;
                #endif
                }

            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const unsigned char* s)
        {
            check_in_var();
            if(check_in_type(otl_var_char,1))
            {

                int overflow;
                otl_strcpy
                    ((unsigned char*)vl[cur_in]->val(),
                    (unsigned char*)s,
                    overflow,
                    vl[cur_in]->elem_size
                    );
                if(overflow)
                {
                    char l_var_info[256];
                    otl_var_info_var
                        (vl[cur_in]->name,
                        vl[cur_in]->ftype,
                        otl_var_char,
                        l_var_info);
                    throw otl_exception
                        (otl_error_msg_4,
                        otl_error_code_4,
                        stm_text,
                        l_var_info);
                #ifndef __SUNPRO_CC
                    return *this;
                #endif
                }

            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const int n)
        {
            check_in_var();
            if(check_in_type(otl_var_int,sizeof(int)))
            {
                *(int*)vl[cur_in]->val()=n;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const unsigned u)
        {
            check_in_var();
            if(check_in_type(otl_var_unsigned_int,sizeof(unsigned)))
            {
                *(unsigned*)vl[cur_in]->val()=u;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const short sh)
        {
            check_in_var();
            if(check_in_type(otl_var_short,sizeof(short)))
            {
                *(short*)vl[cur_in]->val()=sh;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const long int l)
        {
            check_in_var();
            if(check_in_type(otl_var_long_int,sizeof(long)))
            {
                *(long*)vl[cur_in]->val()=l;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const float f)
        {
            check_in_var();
            if(check_in_type(otl_var_float,sizeof(float)))
            {
                *(float*)vl[cur_in]->val()=f;
            }
            get_in_next();
            return *this;
        }

        otl_ref_select_stream& operator<<(const double d)
        {
            check_in_var();
            if(check_in_type(otl_var_double,sizeof(double)))
            {
                *(double*)vl[cur_in]->val()=d;
            }
            get_in_next();
            return *this;
        }

        int select_list_len(void)
        {
            return sl_len;
        }

        int column_ftype(int ndx=0)
        {
            return sl[ndx].ftype;
        }

        int column_size(int ndx=0)
        {
            return sl[ndx].elem_size;
        }

        otl_column_desc* sl_desc;
        int sl_len;
        otl_generic_variable* sl;

    protected:

        int null_fetched;
        int ret_code;
        int cur_col;
        int cur_in;
        int executed;
        char var_info[256];

        void init(void)
        {
            sl=0;
            sl_len=0;
            null_fetched=0;
            ret_code=0;
            sl_desc=0;
            executed=0;
            cur_in=0;
            stm_text=0;
        }

        void get_next(void)
        {
            if(cur_col<sl_len-1)
            {
                ++cur_col;
                null_fetched=sl[cur_col].is_null(cur_row);
            }
            else
            {
                ret_code=next();
                cur_col=0;
            }
        }

        int check_type(int type_code, int actual_data_type=0)
        {
            int out_type_code;
            if(actual_data_type!=0)
                out_type_code=actual_data_type;
            else
                out_type_code=type_code;
            if(sl[cur_col].ftype!=type_code)
            {
                otl_var_info_col
                    (sl[cur_col].pos,
                    sl[cur_col].ftype,
                    out_type_code,
                    var_info);
                throw otl_exception
                    (otl_error_msg_0,
                    otl_error_code_0,
                    stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return 0;
            #endif
            }else
            return 1;
        }

        void look_ahead(void)
        {
            if(cur_col==sl_len-1)
            {
                ret_code=next();
                cur_col=-1;
            }
        }

        void get_select_list(void)
        {
            int i,j,rc;
            otl_column_desc sl_desc_tmp[otl_var_list_size];
            int sld_tmp_len=0;
            int ftype,elem_size;
            OCIBind* bindpp;

            if(!sel_cur.connected)
            {
                sel_cur.open(*adb);
                rc=OCIBindByName
                    (cursor_struct.cda,
                    &bindpp,
                    cursor_struct.errhp,
                    (text*)cur_placeholder,
                    strlen(cur_placeholder),
                    (dvoid*)&sel_cur.cursor_struct.cda,
                    0,
                    SQLT_RSET,
                    (dvoid*)0,
                    (ub2*) 0,
                    (ub2*) 0,
                    (ub4) 0,
                    (ub4*) 0,
                    OCI_DEFAULT);
                if(rc!=0)throw otl_exception(cursor_struct,stm_text);
            }

            for(i=0;i<vl_len;++i)
                otl_tmpl_cursor
                    <otl_exc,
                    otl_conn,
                    otl_cur,
                    otl_var>::bind(*vl[i]);
            otl_tmpl_cursor
                <otl_exc,
                otl_conn,
                otl_cur,
                otl_var>::exec(1);                // Executing the PLSQL master block
            sel_cur.connected=1;
            cur_row=-2;
            sld_tmp_len=0;
            sel_cur.cursor_struct.straight_select=0;
            for(i=1;sel_cur.describe_column(sl_desc_tmp[i-1],i);++i)
                ++sld_tmp_len;
            sl_len=sld_tmp_len;
            if(sl)
            {
                delete[] sl;
                sl=0;
            }
            sl=new otl_generic_variable[sl_len];
            int max_long_size=adb->get_max_long_size();
            for(j=0;j<sl_len;++j)
            {
                otl_generic_variable::map_ftype
                    (sl_desc_tmp[j],max_long_size,ftype,elem_size,*override,j+1);
                sl[j].copy_pos(j+1);
                sl[j].init(ftype,
                    elem_size,
                    (short)array_size,
                    &adb->connect_struct
                    );
            }
            if(sl_desc)
            {
                delete[] sl_desc;
                sl_desc=0;
            }
            sl_desc=new otl_column_desc[sl_len];
            memcpy(sl_desc,sl_desc_tmp,sizeof(otl_column_desc)*sl_len);
            for(i=0;i<sl_len;++i)sel_cur.bind(sl[i]);
        }

        void get_in_next(void)
        {
            if(cur_in==vl_len-1)
                rewind();
            else
            {
                ++cur_in;
                executed=0;
            }
        }

        int check_in_type(int type_code,int tsize)
        {
            if(vl[cur_in]->ftype==otl_var_char&&type_code==otl_var_char)
                return 1;
            if(vl[cur_in]->ftype!=type_code||vl[cur_in]->elem_size!=tsize)
            {
                otl_var_info_var
                    (vl[cur_in]->name,
                    vl[cur_in]->ftype,
                    type_code,
                    var_info);
                throw otl_exception
                    (otl_error_msg_0,
                    otl_error_code_0,
                    stm_text,
                    var_info);
            #ifndef __SUNPRO_CC
                return 1;
            #endif
            }else
            return 1;
        }

        void check_in_var(void)
        {
            if(vl_len==0)
                throw otl_exception
                    (otl_error_msg_1,
                    otl_error_code_1,
                    stm_text,
                    0);
        }

        void check_if_executed(void)
        {
            if(!executed)
                throw otl_exception
                    (otl_error_msg_2,
                    otl_error_code_2,
                    stm_text,
                    0);
        }

};

class otl_stream
{
    public:

        otl_ref_select_stream* ref_ss;
        otl_select_stream* ss;
        otl_inout_stream* io;
        otl_connect* adb;

        int auto_commit_flag;

        otl_var_desc* iov;
        int iov_len;

        otl_var_desc* ov;
        int ov_len;

        otl_select_struct_override override;

        void set_column_type(const int column_ndx,
            const int col_type,
            const int col_size=0)
        {
            override.add_override(column_ndx,col_type,col_size);
        }

        long get_rpc()
        {
            if(io)
                return io->get_rpc();
            else
                return 0;
        }

        void create_var_desc(void)
        {
            int i;
            delete[] iov;
            delete[] ov;
            iov=0; iov_len=0;
            ov=0; ov_len=0;
            if(ss)
            {
                if(ss->vl_len>0)
                {
                    iov=new otl_var_desc[ss->vl_len];
                    iov_len=ss->vl_len;
                    for(i=0;i<ss->vl_len;++i)
                        ss->vl[i]->copy_var_desc(iov[i]);
                }
                if(ss->sl_len>0)
                {
                    ov=new otl_var_desc[ss->sl_len];
                    ov_len=ss->sl_len;
                    for(i=0;i<ss->sl_len;++i)
                        ss->sl[i].copy_var_desc(ov[i]);
                }
            }
            else if(io)
            {
                if(io->vl_len>0)
                {
                    iov=new otl_var_desc[io->vl_len];
                    iov_len=io->vl_len;
                    for(i=0;i<io->vl_len;++i)
                        io->vl[i]->copy_var_desc(iov[i]);
                }
                if(io->iv_len>0)
                {
                    ov=new otl_var_desc[io->iv_len];
                    ov_len=io->iv_len;
                    for(i=0;i<io->iv_len;++i)
                        io->in_vl[i]->copy_var_desc(ov[i]);
                }
            }
            else if(ref_ss)
            {
                if(ref_ss->vl_len>0)
                {
                    iov=new otl_var_desc[ref_ss->vl_len];
                    iov_len=ref_ss->vl_len;
                    for(i=0;i<ref_ss->vl_len;++i)
                        ref_ss->vl[i]->copy_var_desc(iov[i]);
                }
                if(ref_ss->sl_len>0)
                {
                    ov=new otl_var_desc[ref_ss->sl_len];
                    ov_len=ref_ss->sl_len;
                    for(i=0;i<ref_ss->sl_len;++i)
                        ref_ss->sl[i].copy_var_desc(ov[i]);
                }
            }
        }

        otl_stream
            (const short arr_size,
            const char* sqlstm,
            otl_connect& db,
            const char* ref_cur_placeholder=0)
        {
            io=0; ss=0; ref_ss=0;
            iov=0; iov_len=0;
            ov=0; ov_len=0;
            auto_commit_flag=1;
            adb=&db;
            open(arr_size,sqlstm,db,ref_cur_placeholder);
        }

        otl_stream()
        {
            ref_ss=0;
            io=0;
            ss=0;
            adb=0;
            ov=0; ov_len=0;
            auto_commit_flag=1;
            iov=0; iov_len=0;
        }

        ~otl_stream()
        {
            close();
        }

        int eof(void)
        {
            if(io)
                return io->eof();
            else if(ss)
                return ss->eof();
            else if(ref_ss)
                return ref_ss->eof();
            else
                return 1;
        }

        void flush(void)
        {
            if(io)io->flush();
        }

        void clean(const int clean_up_error_flag=0)
        {
            if(io)io->clean(clean_up_error_flag);
        }

        void rewind(void)
        {
            if(io)
                io->rewind();
            else if(ss)
                ss->rewind();
            else if(ref_ss)
                ref_ss->rewind();
        }

        int is_null(void)
        {
            if(io)
                return io->is_null();
            else if(ss)
                return ss->is_null();
            else if(ref_ss)
                return ref_ss->is_null();
            else
                return 0;
        }

        void set_commit(int auto_commit=0)
        {
            auto_commit_flag=auto_commit;
            if(io)io->set_commit(auto_commit);
        }

        void open
            (const short arr_size,
            const char* sqlstm,
            otl_connect& db,
            const char* ref_cur_placeholder=0)
        {
            delete[] iov;
            delete[] ov;

            iov=0; iov_len=0;
            ov=0; ov_len=0;

            char tmp[7];
            char* c=(char*)sqlstm;

            while(isspace(*c))++c;
            strncpy(tmp,c,6);
            tmp[6]=0;
            c=tmp;
            while(*c)
            {
                *c=(char)otl_to_upper(*c);
                ++c;
            }
            adb=&db;
            if(strncmp(tmp,"SELECT",6)==0)
            {
                ss=new otl_select_stream(&override,arr_size,sqlstm,db);
            }
            else if(ref_cur_placeholder!=0)
            {
                ref_ss=new otl_ref_select_stream(&override,arr_size,sqlstm,ref_cur_placeholder,db);
            }
            else
            {
                io=new otl_inout_stream(arr_size,sqlstm,db);
            }
            if(io)io->set_commit(auto_commit_flag);
            create_var_desc();
        }

        void close(void)
        {
            delete[] iov;
            delete[] ov;

            iov=0; iov_len=0;
            ov=0; ov_len=0;

            delete ss;
            delete io;
            delete ref_ss;
            ss=0; io=0; ref_ss=0;
            adb=0;
        }

        otl_column_desc* describe_select(int& desc_len)
        {
            desc_len=0;
            if(ss)
            {
                desc_len=ss->sl_len;
                return ss->sl_desc;
            }
            if(ref_ss)
            {
                desc_len=ref_ss->sl_len;
                return ref_ss->sl_desc;
            }
            return 0;
        }

        int good(void)
        {
            if(io||ss||ref_ss)
                return 1;
            else
                return 0;
        }

        otl_stream& operator>>(otl_pl_tab_generic& tab)
        {
            if(io)io->operator>>(tab);
            return *this;
        }

        otl_stream& operator<<(otl_pl_tab_generic& tab)
        {
            if(io)io->operator<<(tab);
            return *this;
        }

        otl_stream& operator<<(otl_lob_stream& s)
        {
            if(io)io->operator<<(s);
            return *this;
        }

        otl_stream& operator>>(otl_time0& s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator<<(const otl_time0& n)
        {
            if(io)
                io->operator<<(n);
            else if(ss)
                ss->operator<<(n);
            else if(ref_ss)
            {
                ref_ss->operator<<(n);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator>>(otl_datetime& s)
        {
            otl_time0 tmp;
            (*this)>>tmp;
            s.year=((int)tmp.century-100)*100+((int)tmp.year-100);
            s.month=tmp.month;
            s.day=tmp.day;
            s.hour=tmp.hour-1;
            s.minute=tmp.minute-1;
            s.second=tmp.second-1;
            return *this;
        }

        otl_stream& operator<<(const otl_datetime& s)
        {
            otl_time0 tmp;
            tmp.year=(s.year%100)+100;
            tmp.century=(s.year/100)+100;
            tmp.month=s.month;
            tmp.day=s.day;
            tmp.hour=s.hour+1;
            tmp.minute=s.minute+1;
            tmp.second=s.second+1;
            (*this)<<tmp;
            return *this;
        }

        otl_stream& operator>>(char& c)
        {
            if(io)
                io->operator>>(c);
            else if(ss)
                ss->operator>>(c);
            else if(ref_ss)
                ref_ss->operator>>(c);
            return *this;
        }

        otl_stream& operator>>(unsigned char& c)
        {
            if(io)
                io->operator>>(c);
            else if(ss)
                ss->operator>>(c);
            else if(ref_ss)
                ref_ss->operator>>(c);
            return *this;
        }

        otl_stream& operator>>(char* s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator>>(unsigned char* s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator>>(int& n)
        {
            if(io)
                io->operator>>(n);
            else if(ss)
                ss->operator>>(n);
            else if(ref_ss)
                ref_ss->operator>>(n);
            return *this;
        }

        otl_stream& operator>>(unsigned& u)
        {
            if(io)
                io->operator>>(u);
            else if(ss)
                ss->operator>>(u);
            else if(ref_ss)
                ref_ss->operator>>(u);
            return *this;
        }

        otl_stream& operator>>(short& sh)
        {
            if(io)
                io->operator>>(sh);
            else if(ss)
                ss->operator>>(sh);
            else if(ref_ss)
                ref_ss->operator>>(sh);
            return *this;
        }

        otl_stream& operator>>(long int& l)
        {
            if(io)
                io->operator>>(l);
            else if(ss)
                ss->operator>>(l);
            else if(ref_ss)
                ref_ss->operator>>(l);
            return *this;
        }

        otl_stream& operator>>(float& f)
        {
            if(io)
                io->operator>>(f);
            else if(ss)
                ss->operator>>(f);
            else if(ref_ss)
                ref_ss->operator>>(f);
            return *this;
        }

        otl_stream& operator>>(double& d)
        {
            if(io)
                io->operator>>(d);
            else if(ss)
                ss->operator>>(d);
            else if(ref_ss)
                ref_ss->operator>>(d);
            return *this;
        }

        otl_stream& operator>>(otl_long_string& s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator>>(otl_lob_stream& s)
        {
            if(io)
                io->operator>>(s);
            else if(ss)
                ss->operator>>(s);
            else if(ref_ss)
                ref_ss->operator>>(s);
            return *this;
        }

        otl_stream& operator<<(const char c)
        {
            if(io)
                io->operator<<(c);
            else if(ss)
                ss->operator<<(c);
            else if(ref_ss)
            {
                ref_ss->operator<<(c);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const unsigned char c)
        {
            if(io)
                io->operator<<(c);
            else if(ss)
                ss->operator<<(c);
            else if(ref_ss)
            {
                ref_ss->operator<<(c);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const char* s)
        {
            if(io)
                io->operator<<(s);
            else if(ss)
                ss->operator<<(s);
            else if(ref_ss)
            {
                ref_ss->operator<<(s);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const unsigned char* s)
        {
            if(io)
                io->operator<<(s);
            else if(ss)
                ss->operator<<(s);
            else if(ref_ss)
            {
                ref_ss->operator<<(s);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const int n)
        {
            if(io)
                io->operator<<(n);
            else if(ss)
                ss->operator<<(n);
            else if(ref_ss)
            {
                ref_ss->operator<<(n);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const unsigned u)
        {
            if(io)
                io->operator<<(u);
            else if(ss)
                ss->operator<<(u);
            else if(ref_ss)
            {
                ref_ss->operator<<(u);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const short sh)
        {
            if(io)
                io->operator<<(sh);
            else if(ss)
                ss->operator<<(sh);
            else if(ref_ss)
            {
                ref_ss->operator<<(sh);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const long int l)
        {
            if(io)
                io->operator<<(l);
            else if(ss)
                ss->operator<<(l);
            else if(ref_ss)
            {
                ref_ss->operator<<(l);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const float f)
        {
            if(io)
                io->operator<<(f);
            else if(ss)
                ss->operator<<(f);
            else if(ref_ss)
            {
                ref_ss->operator<<(f);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const double d)
        {
            if(io)
                io->operator<<(d);
            else if(ss)
                ss->operator<<(d);
            else if(ref_ss)
            {
                ref_ss->operator<<(d);
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const otl_null n)
        {
            OTL_UNUSED_ARG(n)
                if(io)io->operator<<(otl_null());
            if(ss)ss->operator<<(otl_null());
            if(ref_ss)
            {
                ref_ss->operator<<(otl_null());
                if(!ov&&ref_ss->sl) create_var_desc();
            }
            return *this;
        }

        otl_stream& operator<<(const otl_long_string& d)
        {
            if(io)io->operator<<(d);
            return *this;
        }

};

typedef otl_tmpl_nocommit_stream<otl_stream,otl_connect> otl_nocommit_stream;

OTL_ORA8_NAMESPACE_END
#ifndef __STDC__DEFINED
#undef __STDC__
#endif
#endif

#ifdef OTL_DATA_CONT

// ====== DATA CONTAINER CLASSES FOR READING FROM/WRITING TO OTL STREAMS ======
//
// These data container classes read/write values from/to OTL stream
// together with the NULL indicators. Also, <</>> operators are
// defined for the data containers.

template <class TData>
class otl_host_var
{
    public:
        TData v;
        short int ind;

        otl_host_var(){ind=0;}
        ~otl_host_var(){}

        otl_host_var& operator=(const otl_host_var& var)
        {
            v=var.v;
            ind=var.ind;
            return *this;
        }

        otl_host_var(const otl_host_var& var)
        {
            v=var.v;
            ind=var.ind;
        }

        otl_host_var& operator=(const TData& var)
        {
            v=var;
            ind=0;
            return *this;
        }

        int is_null(void){return ind;}
        const
            void set_null(void){ind=1;}
        void set_non_null(void){ind=0;}

};

template <class T>
inline bool operator==(const otl_host_var<T>& x, const otl_host_var<T>& y)
{
    return !x.ind&&!y.ind&&x.v-y.v<0.001||y.v-x.v<0.001||x.ind&&y.ind;
}


typedef otl_host_var<int> otl_host_int;
typedef otl_host_var<double> otl_host_double;
typedef otl_host_var<float> otl_host_float;
typedef otl_host_var<unsigned int> otl_host_unsigned;
typedef otl_host_var<short int> otl_host_short;
typedef otl_host_var<long int> otl_host_long_int;
typedef otl_host_var<char> otl_host_char;
typedef otl_host_var<otl_datetime> otl_host_datetime;

template <class base_char, const int size>
class otl_base_host_string
{
    public:

        base_char v[size];
        short int ind;

        otl_base_host_string(){ind=0;}
        ~otl_base_host_string(){}

        otl_base_host_string& operator=(const otl_base_host_string& var)
        {
            strcpy(v,var.v);
            ind=var.ind;
            return *this;
        }

        otl_base_host_string(const otl_base_host_string& var)
        {
            strcpy(v,var.v);
            ind=var.ind;
        }

        otl_base_host_string& operator=(const base_char* str)
        {
            strcpy(v,str);
            ind=0;
            return *this;
        }

        int is_null(void){return ind;}
        void set_null(void){ind=1;}
        void set_non_null(void){ind=0;}

};

template <const int size>
struct otl_host_string: public otl_base_host_string<char,size>
{

    otl_host_string():otl_base_host_string<char,size>(){}
    ~otl_host_string(){}

    otl_host_string& operator=(const otl_host_string& var)
    {

        strcpy(v,var.v);
        ind=var.ind;
        return *this;
    }

    otl_host_string(const otl_host_string& var)
        :otl_base_host_string<char,size>(var){}

    otl_host_string& operator=(const char* str)
    {
        strcpy(v,str);
        ind=0;
        return *this;
    }

};

template <const int size>
struct otl_host_ustring: public otl_base_host_string<unsigned char,size>
{

    otl_host_ustring():otl_base_host_string<unsigned char,size>(){}
    ~otl_host_ustring(){}

    otl_host_ustring& operator=(const otl_host_ustring& var)
    {
        strcpy(v,var.v);
        ind=var.ind;
        return *this;
    }

    otl_host_ustring(const otl_host_ustring& var)
        :otl_base_host_string<unsigned char,size>(var){}

    otl_host_ustring& operator=(const unsigned char* str)
    {
        strcpy((char*)v,(char*)str);
        ind=0;
        return *this;
    }

};

template <const int size>
inline bool operator==(const otl_host_string<size>& x,
const otl_host_string<size>& y)
{
    return !x.ind&&!y.ind&&strcmp(x.v,y.v)==0||
        x.ind&&y.ind;
}


#ifdef OTL_ORA7
// Oracle 7 compatible stream operators for the data container classes
template <class T>
OTL_ORA7_NAMESPACE_PREFIX otl_stream& operator>>
(OTL_ORA7_NAMESPACE_PREFIX otl_stream& s,
otl_host_var<T>& var)
{
    s>>var.v;
    if(s.is_null())
        var.set_null();
    else
        var.set_non_null();
    return s;
}


template <class T>
OTL_ORA7_NAMESPACE_PREFIX otl_stream& operator<<
(OTL_ORA7_NAMESPACE_PREFIX otl_stream& s,
const otl_host_var<T>& var)
{
    if(var.ind)
        s<<otl_null();
    else
        s<<var.v;
    return s;
}


template <class T,const int size>
OTL_ORA7_NAMESPACE_PREFIX otl_stream& operator>>
(OTL_ORA7_NAMESPACE_PREFIX otl_stream& s,
otl_base_host_string<T,size>& var)
{
    s>>var.v;
    if(s.is_null())
        var.ind=1;
    else
        var.ind=0;
    return s;
}


template <class T,const int size>
OTL_ORA7_NAMESPACE_PREFIX otl_stream& operator<<
(OTL_ORA7_NAMESPACE_PREFIX otl_stream& s,
const otl_base_host_string<T,size>& var)
{
    if(var.ind)
        s<<otl_null();
    else
        s<<var.v;
    return s;
}
#endif

#ifdef OTL_ORA8
// Oracle 8 compatible stream operators for the data container classes
template <class T>
OTL_ORA8_NAMESPACE_PREFIX otl_stream& operator>>
(OTL_ORA8_NAMESPACE_PREFIX otl_stream& s,
otl_host_var<T>& var)
{
    s>>var.v;
    if(s.is_null())
        var.set_null();
    else
        var.set_non_null();
    return s;
}


template <class T>
OTL_ORA8_NAMESPACE_PREFIX otl_stream& operator<<
(OTL_ORA8_NAMESPACE_PREFIX otl_stream& s,
const otl_host_var<T>& var)
{
    if(var.ind)
        s<<otl_null();
    else
        s<<var.v;
    return s;
}


template <class T,const int size>
OTL_ORA8_NAMESPACE_PREFIX otl_stream& operator>>
(OTL_ORA8_NAMESPACE_PREFIX otl_stream& s,
otl_base_host_string<T,size>& var)
{
    s>>var.v;
    if(s.is_null())
        var.ind=1;
    else
        var.ind=0;
    return s;
}


template <class T,const int size>
OTL_ORA8_NAMESPACE_PREFIX otl_stream& operator<<
(OTL_ORA8_NAMESPACE_PREFIX otl_stream& s,
const otl_base_host_string<T,size>& var)
{
    if(var.ind)
        s<<otl_null();
    else
        s<<var.v;
    return s;
}
#endif

#ifdef OTL_ODBC
// ODBC compatible stream operators for the data container classes
template <class T>
OTL_ODBC_NAMESPACE_PREFIX otl_stream& operator>>
(OTL_ODBC_NAMESPACE_PREFIX otl_stream& s,
otl_host_var<T>& var)
{
    s>>var.v;
    if(s.is_null())
        var.set_null();
    else
        var.set_non_null();
    return s;
}


template <class T>
OTL_ODBC_NAMESPACE_PREFIX otl_stream& operator<<
(OTL_ODBC_NAMESPACE_PREFIX otl_stream& s,
const otl_host_var<T>& var)
{
    if(var.ind)
        s<<otl_null();
    else
        s<<var.v;
    return s;
}


template <class T,const int size>
OTL_ODBC_NAMESPACE_PREFIX otl_stream& operator>>
(OTL_ODBC_NAMESPACE_PREFIX otl_stream& s,
otl_base_host_string<T,size>& var)
{
    s>>var.v;
    if(s.is_null())
        var.ind=1;
    else
        var.ind=0;
    return s;
}


template <class T,const int size>
OTL_ODBC_NAMESPACE_PREFIX otl_stream& operator<<
(OTL_ODBC_NAMESPACE_PREFIX otl_stream& s,
const otl_base_host_string<T,size>& var)
{
    if(var.ind)
        s<<otl_null();
    else
        s<<var.v;
    return s;
}
#endif

// template <class T>
// ostream& operator<<(ostream& s, const otl_host_var<T>& var)
// {
//  if(var.ind==1)
//   s<<"NULL";
//  else
//   s<<var.v;
//  return s;
// }

// template <class T,const int size>
// ostream& operator<<(ostream& s, const otl_base_host_string<T,size>& var)
// {
//  if(var.ind==1)
//   s<<"NULL";
//  else
//   s<<(char*)var.v;
//  return s;
// }
#endif
#endif
